From a648c9b665fe2ea789cd11009b35ba01c8000072 Mon Sep 17 00:00:00 2001 From: Denis Groshev Date: Mon, 9 Nov 2026 00:22:12 +0100 Subject: [PATCH 01/12] feat(satellites): owner, operator and COSPAR groundwork for the orbital view The orbital view reads a satellite's owner country, operator, COSPAR id, TLE epoch and whether its class can be ridden. #1558 now carries only what the class toggles read, so this brings the rest back here, where it is first used: the classes.js helpers and the UCS pack's operator and owner fields. --- DATA_SOURCES.md | 4 +- docs/CURRENT-STATE.md | 2 +- scripts/build-ucs-satellites.py | 16 +- src/data/dataCredits.js | 2 +- src/data/local_data/ucs_satellites/README.md | 32 +- .../ucs_satellites/ucs_satellites.json | 2 +- src/data/ucsSatellites.js | 11 +- src/data/ucsSatellites.test.mjs | 34 +- src/layers/satellites/catalog.js | 2 + src/layers/satellites/classes.js | 450 +++++++++++++++++- src/layers/satellites/classes.test.mjs | 206 ++++---- src/layers/satellites/ingestion.js | 2 + src/layers/satellites/state.js | 2 +- 13 files changed, 617 insertions(+), 148 deletions(-) diff --git a/DATA_SOURCES.md b/DATA_SOURCES.md index 7e11d6a03..52f72641c 100644 --- a/DATA_SOURCES.md +++ b/DATA_SOURCES.md @@ -229,7 +229,7 @@ The [Bhote Koshi event pack](public/events/bhote-koshi-2026/README.md), under `p | **Québec CCTV source catalog** (1,120 locations) | `public/quebec-cameras.json` | Mixed: MTQ locations CC BY 4.0; Montréal camera nodes ODbL 1.0; scenic records retain per-record provenance. No video files are bundled or cached. | Location data is per-record; video remains hosted by Québec 511 and its platform terms apply; scenic source pages may have separate terms | MTQ / Données Québec CC BY 4.0; © OpenStreetMap contributors (ODbL); scenic operator and position source shown in the selected-camera panel | | **World camera image subset** (2,230 locations) | `config/cctv_sources.world-image-cameras.json` | Mixed: ODOT TripCheck public images (ODOT permits use with credit) and MLIT site content under terms compatible with CC BY 4.0. Frames are not bundled or persisted; the server holds a bounded in-memory cache. | Per-source terms apply; NZTA Journey Planner web-cache rows are excluded; Vegagerðin rows are served by the Iceland pack instead | Oregon Department of Transportation (Camera courtesy of ODOT) and Japan Ministry of Land, Infrastructure, Transport and Tourism (出典:国土交通省 川の防災情報) | | **TeleGeography Submarine Cable Map** (712 cables + 1,917 landing points) | `telegeography_submarine_cables/` | **CC BY-NC-SA 3.0** | ❌ **NonCommercial — remove for commercial use** | "© TeleGeography — submarinecablemap.com" | -| **UCS Satellite Database** UCS-Satellite-Database 5-1-2023 (3,564 records; purpose) | `ucs_satellites/` | **Free, unrestricted use** (UCS database manual, section 3) | ✅ (acknowledgement requested) | "UCS Satellite Database (UCS-Satellite-Database 5-1-2023), https://www.ucsusa.org/satellite_database" | +| **UCS Satellite Database** UCS-Satellite-Database 5-1-2023 (3,564 records; operator, owner country, purpose) | `ucs_satellites/` | **Free, unrestricted use** (UCS database manual, section 3) | ✅ (acknowledgement requested) | "UCS Satellite Database (UCS-Satellite-Database 5-1-2023), https://www.ucsusa.org/satellite_database" | | **Natural Earth physical regions** (1,046 land + 292 marine named polygons) | `natural_earth/` | **Public domain** | ✅ (no restrictions) | "Made with Natural Earth" (courtesy credit — not legally required) | | **DataSF Analysis Neighborhoods** (41 SF neighborhood polygons) | `neighborhoods/` | **PDDL 1.0** (public domain) | ✅ (no restrictions) | "City & County of San Francisco — DataSF" (courtesy — not legally required) | | **Natural Earth countries, states and provinces** (260 admin-0/map units + 4,587 admin-1 polygons) | `natural_earth/` | **Public domain** | ✅ (no restrictions) | "Made with Natural Earth" (courtesy credit — not legally required) | @@ -296,7 +296,7 @@ The former bundled 2026-05-25 snapshot was removed 2026-07-16. ### UCS Satellite Database (`ucs_satellites/`) -The purpose of each active satellite, keyed by NORAD number, from the Union of Concerned Scientists Satellite Database release **UCS-Satellite-Database 5-1-2023** (data current through 2023-05-01; https://www.ucsusa.org/satellite_database). The satellites layer joins it to CelesTrak positions and SATCAT records to file each satellite as a station, imaging, telecom, Starlink, probe or debris object. Section 3 of the UCS database manual: "The Database is free and its use is unrestricted. We request that its use be acknowledged and referenced in written materials. References should include the version of the Database that was used, which is indicated by the name of the Excel file, and a link to or URL for the webpage www.ucsusa.org/satellite_database." The app acknowledges it in the Data attribution popover. UCS has paused updates since this release; Starlink rows are dropped (Starlink is classed by name). Build: `scripts/build-ucs-satellites.py`; curation in the folder README. +Operator, owner country and purpose for active satellites, keyed by NORAD number, from the Union of Concerned Scientists Satellite Database release **UCS-Satellite-Database 5-1-2023** (data current through 2023-05-01; https://www.ucsusa.org/satellite_database). The satellites layer joins it to CelesTrak positions and SATCAT records to file each satellite as a station, imaging, telecom, Starlink, probe or debris object, and to name its operator and owner. Section 3 of the UCS database manual: "The Database is free and its use is unrestricted. We request that its use be acknowledged and referenced in written materials. References should include the version of the Database that was used, which is indicated by the name of the Excel file, and a link to or URL for the webpage www.ucsusa.org/satellite_database." The app acknowledges it in the Data attribution popover. UCS has paused updates since this release; Starlink rows are dropped (Starlink is classed by name). Build: `scripts/build-ucs-satellites.py`; curation in the folder README. ### Natural Earth physical regions (`natural_earth/`) diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 4ddc05b45..ab92553b2 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -5458,7 +5458,7 @@ silently demoting every later lookup for the session. - **Satellite classes** (`src/layers/satellites/classes.js`): every satellite is filed under one of six classes, each with its own point colour, legend swatch and toggle: STATIONS (warm white), IMAGING (cyan), TELECOM (violet; communications and navigation, so GPS, GLONASS, Galileo and BeiDou read as one family), STARLINK (dim slate), PROBES (muted blue-gray) and DEBRIS (receding brown-gray). That module is the single source of truth for class, label and colour, so the dot, the card and the legend swatch cannot disagree. Two deliberate palette rules: no class may sit in the 40–48° amber band, which is the app-wide known-military convention; and STARLINK stays far below PROBES in Rec.601 luminance so the dense shell stays separable when NVG/FLIR collapse the scene to one channel. The ISS keeps its long-standing red hero dot rather than the STATIONS colour — it carries a permanent name label and its card still reads `STATIONS · ISS`; it is a station whichever group ingested it, so a stations-feed outage cannot refile it. `src/data/satelliteClass.js` keeps the group-based labels beneath the classes: the constellation subtype and a group's own label for a satellite with no class. - Class is also a **text field**, not just a color: `TELECOM · GPS` / `STARLINK` / `STATIONS · ISS` leads the tracked card's detail block and replaces the raw CelesTrak tag on the detection-overlay label. Because that canvas composites above the post-FX chain, the class stays readable in NVG/FLIR after the in-scene dot colors are flattened. - The satellites row in DATA LAYERS carries per-layer sub-controls (`DataLayerManager._syncRowControls`, the first consumer of the optional `getRowControls()` layer hook): one chip per class (the STARLINK chip exposes the existing `catalog` param), a swatch legend with live per-class counts, and an info line while SATCAT is stale or unavailable (`Classes may lag: SATCAT is a cached copy` / `Classes may lag: SATCAT unavailable`). Default is the sparse core catalog. The chips are stateless — each declares the params to apply and the manager owns the write — so the Space Missions capture/restore path over the same param stays authoritative. Controls stay hidden while the layer is off. An explicit CORE or DENSE choice participates in versioned local and share-link state; temporary Space Missions overrides do not. -- **Class toggles** (`src/layers/satellites/classes.js`): the layer row carries one chip per class — STATIONS, IMAGING, TELECOM (communications and navigation), PROBES (science, technology development and demonstration, unknown purpose) and DEBRIS (rocket bodies, fragments, unknown objects launched before last year and dead payloads) on by default, so the layer shows what it did before classes; STARLINK off, as DENSE was. Points of a hidden class stay built and are only hidden, so a toggle needs no reload; hidden classes are left out of the detection overlay, the voice/framing position lists and analyst answers (the tracked satellite still answers), and the legend keys only the classes on screen. The class comes, strongest evidence first, from CelesTrak SATCAT (object type and operational status, fetched per group through `/api/celestrak-satcat/`, cached a day by the proxy; the layer keeps a current read six hours rather than asking on every five-minute update), the bundled UCS Satellite Database pack (UCS-Satellite-Database 5-1-2023: each satellite's purpose; `src/data/local_data/ucs_satellites/`), name patterns for satellites launched after May 2023, and finally the CelesTrak groups the TLE came in (a mission group such as `weather` before the orbit group `geo`; a UCS purpose of "Unknown" counts as none). Only crewed stations and the craft that visit them, by name, are STATIONS: the CubeSats CelesTrak's stations group also carries after their deployment from the ISS are classed like any other satellite. A payload whose SATCAT record gives no status, with no UCS record and no recognisable name, that launched 20 or more years ago (SATCAT's launch date, else the TLE designator's year) is presumed dead and filed as debris; without a SATCAT record (a failed read) nothing is presumed. To cover imaging launched after the UCS snapshot the core catalog also reads CelesTrak's `resource`, `weather`, `planet`, `sar` and `science` groups. Retired stations and the shuttles have re-entered and have no orbit to show. An explicit class choice is kept in local and share-link state as the `classes` option, one letter per class shown (`sitpd`: stations, imaging, telecom, probes, debris; `0`: none; `src/data/satelliteClassMask.js`), and the layer takes those letters back through `setParams({classes})`; STARLINK maps to the existing `catalog: 'dense'` param instead. +- **Class toggles** (`src/layers/satellites/classes.js`): the layer row carries one chip per class — STATIONS, IMAGING, TELECOM (communications and navigation), PROBES (science, technology development and demonstration, unknown purpose) and DEBRIS (rocket bodies, fragments, unknown objects launched before last year and dead payloads) on by default, so the layer shows what it did before classes; STARLINK off, as DENSE was. Points of a hidden class stay built and are only hidden, so a toggle needs no reload; hidden classes are left out of the detection overlay, the voice/framing position lists and analyst answers (the tracked satellite still answers), and the legend keys only the classes on screen. The class comes, strongest evidence first, from CelesTrak SATCAT (object type and operational status, fetched per group through `/api/celestrak-satcat/`, cached a day by the proxy; the layer keeps a current read six hours rather than asking on every five-minute update), the bundled UCS Satellite Database pack (UCS-Satellite-Database 5-1-2023: operator, owner country and purpose; `src/data/local_data/ucs_satellites/`), name patterns for satellites launched after May 2023, and finally the CelesTrak groups the TLE came in (a mission group such as `weather` before the orbit group `geo`; a UCS purpose of "Unknown" counts as none). Only crewed stations and the craft that visit them, by name, are STATIONS: the CubeSats CelesTrak's stations group also carries after their deployment from the ISS are classed like any other satellite. A payload whose SATCAT record gives no status, with no UCS record and no recognisable name, that launched 20 or more years ago (SATCAT's launch date, else the TLE designator's year) is presumed dead and filed as debris; without a SATCAT record (a failed read) nothing is presumed. To cover imaging launched after the UCS snapshot the core catalog also reads CelesTrak's `resource`, `weather`, `planet`, `sar` and `science` groups. Retired stations and the shuttles have re-entered and have no orbit to show. An explicit class choice is kept in local and share-link state as the `classes` option, one letter per class shown (`sitpd`: stations, imaging, telecom, probes, debris; `0`: none; `src/data/satelliteClassMask.js`), and the layer takes those letters back through `setParams({classes})`; STARLINK maps to the existing `catalog: 'dense'` param instead. - **The STARLINK chip (formerly DENSE) reports the dense LOAD, not the catalog param.** The param flips synchronously while the Starlink shell takes seconds to arrive over a chunked load, and CelesTrak 502s that feed regularly. So the chip reads `STARLINK ···` (busy, disabled) while loading, ACTIVE only once dense points are actually on screen, and `STARLINK ✕` with the reason on hover when the load fails — a failure also reverts `catalog` to `core`, drops any partial chunk, and leaves the chip clickable to retry. A load is judged by points added, not by HTTP status: a 200 carrying an empty body, a passed-through HTML error page, or only TLEs the core catalog already owns fails with the same revert semantics as a 502. Any explicit request for `core` clears a latched error even when the mode does not change, so a Space Missions restore of an already-core snapshot never leaves the user with a failure they did not cause. Because the load settles asynchronously, the layer pushes a re-render through the optional `setRowControlsListener()` hook; nothing else would repaint that row before the 5-minute catalog refresh, so the count and legend would otherwise sit stale. - **A dependency owner takes the row with it.** Space Missions borrows this layer for TLE lookup with `showPoints:false`; while points are hidden the layer returns empty row controls, so the legend never describes an empty sky and the chip cannot accept a write that the owner's restore would silently revert. - The detection-overlay record cache (`_detectionObjects`) is cleared with the catalog on every rebuild: it stamps id/class at creation only, and a rebuild can re-tag a satellite when a partial CelesTrak outage changes which group wins dedupe. diff --git a/scripts/build-ucs-satellites.py b/scripts/build-ucs-satellites.py index cd7080fb3..d1a0b6fd8 100644 --- a/scripts/build-ucs-satellites.py +++ b/scripts/build-ucs-satellites.py @@ -2,9 +2,9 @@ '''Maintainer-only UCS Satellite Database pack build (openpyxl). Reads the UCS Excel release and writes the compact pack the satellites layer -loads: one row per satellite, keyed by NORAD number, with a string-table index -for its purpose, the one column the layer's classes read. Starlink rows are -left out: the layer files every STARLINK object under its own class by name. +loads: one row per satellite, keyed by NORAD number, with string-table indexes +for the repeated text columns. Starlink rows are left out: the layer files +every STARLINK object under its own class and operator without them. Usage: python scripts/build-ucs-satellites.py "/UCS-Satellite-Database 5-1-2023.xlsx" ''' @@ -26,7 +26,12 @@ URL = 'https://www.ucsusa.org/satellite_database' # Output column -> spreadsheet header. COLUMNS = { + 'operator': 'Operator/Owner', + 'operatorCountry': 'Country of Operator/Owner', 'purpose': 'Purpose', + 'detailedPurpose': 'Detailed Purpose', + 'users': 'Users', + 'orbitClass': 'Class of Orbit', } STARLINK = re.compile(r'\bstarlink\b', re.I) @@ -60,12 +65,11 @@ def build(xlsx: Path) -> dict: except (TypeError, ValueError): invalid_norad += 1 continue - if norad <= 0: - invalid_norad += 1 - continue record = [norad] for key, column in COLUMNS.items(): text = clean(row[header[column]]) + if key == 'orbitClass': + text = text.upper() if text not in index[key]: index[key][text] = len(tables[key]) tables[key].append(text) diff --git a/src/data/dataCredits.js b/src/data/dataCredits.js index a30d7c2b5..a55bed9e4 100644 --- a/src/data/dataCredits.js +++ b/src/data/dataCredits.js @@ -150,7 +150,7 @@ export const DATA_CREDITS = [ { key: 'ucs-satellite-database', html: - 'Satellite purposes: ' + + 'Satellite operators and purposes: ' + 'UCS Satellite Database ' + '(UCS-Satellite-Database 5-1-2023), Union of Concerned Scientists', }, diff --git a/src/data/local_data/ucs_satellites/README.md b/src/data/local_data/ucs_satellites/README.md index 4e2a0cbb0..26cb06607 100644 --- a/src/data/local_data/ucs_satellites/README.md +++ b/src/data/local_data/ucs_satellites/README.md @@ -1,8 +1,9 @@ # UCS Satellite Database pack -Offline purpose records for active satellites, keyed by NORAD catalog number. -The satellites layer joins them to CelesTrak's positions to file each -satellite under a class (stations, imaging, telecom, probes) +Offline operator, owner-country and purpose records for active satellites, +keyed by NORAD catalog number. The satellites layer joins them to CelesTrak's +positions to file each satellite under a class (stations, imaging, telecom, +probes) and to name its operator and owner country (`src/data/ucsSatellites.js`, `src/layers/satellites/classes.js`). | File | Source dataset | Records | @@ -23,7 +24,7 @@ the version of the Database that was used, which is indicated by the name of the Excel file, and a link to or URL for the webpage www.ucsusa.org/satellite_database." -**Acknowledgement:** "Satellite purposes: UCS Satellite Database +**Acknowledgement:** "Satellite operators and purposes: UCS Satellite Database (UCS-Satellite-Database 5-1-2023), https://www.ucsusa.org/satellite_database". It is also listed in the app's Data attribution popover and in DATA_SOURCES.md. @@ -33,13 +34,18 @@ DATA_SOURCES.md. **Curation:** -- Kept column: Purpose, the one the classes read. Everything else - (operators, owners, orbits, masses, contractors, launch data, sources) is - left out. +- Kept columns: Operator/Owner, Country of Operator/Owner, Purpose, Detailed + Purpose, Users, Class of Orbit (upper-cased, which folds the source's one + `LEo`). Everything else (masses, contractors, launch data, sources) is left + out. - Repeated text is stored once in `strings`; each record is - `[noradId, purpose]` with a string-table index, `0` meaning empty. -- The 3,996 Starlink rows are dropped: every Starlink object is classed by - name, so they would only add size. -- Rows without a readable, positive NORAD number are dropped and counted apart - from duplicate NORAD numbers (the first row of a duplicate is kept); both - counts are 0 in this release. + `[noradId, operator, operatorCountry, purpose, detailedPurpose, users, + orbitClass]` with string-table indexes, `0` meaning empty. +- The 3,996 Starlink rows are dropped: every Starlink object is classed and + credited to SpaceX by name, so they would only add size. +- Rows without a readable NORAD number are dropped and counted apart from + duplicate NORAD numbers (the first row of a duplicate is kept); both counts + are 0 in this release. +- Owner countries stay as UCS writes them ("USA", "USA/Japan", "ESA", + "Multinational"); `src/layers/satellites/classes.js` normalises them, together with + CelesTrak SATCAT owner codes, in one table. diff --git a/src/data/local_data/ucs_satellites/ucs_satellites.json b/src/data/local_data/ucs_satellites/ucs_satellites.json index 398fd2db9..f27ee92d8 100644 --- a/src/data/local_data/ucs_satellites/ucs_satellites.json +++ b/src/data/local_data/ucs_satellites/ucs_satellites.json @@ -1 +1 @@ -{"meta":{"source":"Union of Concerned Scientists Satellite Database","version":"UCS-Satellite-Database 5-1-2023","url":"https://www.ucsusa.org/satellite_database","dataCurrentTo":"2023-05-01","license":"Free, unrestricted use; acknowledgement requested (UCS database manual, section 3)","curation":{"sourceRows":7560,"starlinkRowsDropped":3996,"invalidNoradDropped":0,"duplicateNoradDropped":0,"columns":{"purpose":"Purpose"}},"recordCount":3564},"fields":["noradId","purpose"],"strings":{"purpose":["","Earth Observation","Technology Development","Communications","Earth Science","Space Science","Space Science/Technology Demonstration","Communications/Technology Development","Communications/Maritime Tracking","Technology Demonstration","Unknown","Navigation/Global Positioning","Earth Observation/Technology Development","Earth Observation/Communications","Earth/Space Observation","Educational","Earth Observation/Earth Science","Platform","Earth Observation/Space Science","Earth Observation/Navigation","Communications/Navigation","Space Observation","Surveillance","Navigation/Regional Positioning","Space Science/Technology Development","Mission Extension Technology","Earth Science/Earth Observation","Earth Observation/Communications/Space Science","Meteorological","Technology Development/Educational","Satellite Positioning"]},"records":[[7530,3],[19548,3],[20253,3],[20580,5],[20776,3],[21639,3],[22049,5],[22314,3],[22491,1],[22787,3],[22988,3],[23223,1],[23467,3],[23553,3],[23613,3],[23628,3],[23855,1],[23893,3],[24674,3],[24753,1],[24812,3],[24876,11],[24916,3],[24920,1],[24936,3],[25019,3],[25034,1],[25071,3],[25112,3],[25113,3],[25114,3],[25115,3],[25116,3],[25117,3],[25118,3],[25119,3],[25153,3],[25159,3],[25258,3],[25336,1],[25338,1],[25414,3],[25415,3],[25416,3],[25418,3],[25419,3],[25420,3],[25462,3],[25475,3],[25477,3],[25481,3],[25504,1],[25544,5],[25639,3],[25652,3],[25682,1],[25757,4],[25867,5],[25924,3],[25933,11],[25967,3],[25980,3],[25981,3],[25982,3],[25984,3],[25985,3],[25989,5],[25991,1],[25994,1],[26038,3],[26052,3],[26107,3],[26356,1],[26360,11],[26369,3],[26388,3],[26390,3],[26407,11],[26410,5],[26411,5],[26451,3],[26463,5],[26464,5],[26469,3],[26473,1],[26483,3],[26554,3],[26575,3],[26580,3],[26590,3],[26605,11],[26608,3],[26624,3],[26626,3],[26638,3],[26690,11],[26694,3],[26702,1],[26715,3],[26719,3],[26766,3],[26824,3],[26853,3],[26880,1],[26900,3],[26958,9],[26959,12],[26998,5],[27004,2],[27056,3],[27057,3],[27168,3],[27378,3],[27380,3],[27389,3],[27399,3],[27400,3],[27414,3],[27424,1],[27426,3],[27434,1],[27438,3],[27445,3],[27460,3],[27464,3],[27465,3],[27509,1],[27513,3],[27528,3],[27540,5],[27566,3],[27603,3],[27606,3],[27607,3],[27612,3],[27640,1],[27651,5],[27663,11],[27691,3],[27704,11],[27711,3],[27715,3],[27811,3],[27825,3],[27831,3],[27843,5],[27848,2],[27854,3],[27858,5],[27868,3],[27869,3],[27875,3],[27937,1],[27939,2],[27954,3],[28051,1],[28054,1],[28058,3],[28089,3],[28117,3],[28158,1],[28184,3],[28187,3],[28190,11],[28220,1],[28252,3],[28358,3],[28366,7],[28369,2],[28370,2],[28371,1],[28372,7],[28376,1],[28378,3],[28384,3],[28413,5],[28414,5],[28419,3],[28420,3],[28446,3],[28470,1],[28474,11],[28485,5],[28492,1],[28493,3],[28526,3],[28537,1],[28541,1],[28542,3],[28626,3],[28628,3],[28646,1],[28649,1],[28654,1],[28659,3],[28702,3],[28707,3],[28737,5],[28786,3],[28790,3],[28810,2],[28868,3],[28874,11],[28884,3],[28885,3],[28888,1],[28890,1],[28899,3],[28903,3],[28908,3],[28912,1],[28924,3],[28935,3],[28945,3],[28946,3],[29045,3],[29047,1],[29048,1],[29050,1],[29051,1],[29052,1],[29055,3],[29079,1],[29107,1],[29108,4],[29155,1],[29162,3],[29236,3],[29249,1],[29252,2],[29268,12],[29270,3],[29272,3],[29273,3],[29349,3],[29479,5],[29486,11],[29494,3],[29495,3],[29505,5],[29506,5],[29520,3],[29522,1],[29526,3],[29601,11],[29643,3],[29644,3],[29658,1],[29670,11],[29671,11],[29709,12],[29710,1],[30580,5],[30776,2],[30794,3],[30797,5],[30798,5],[31102,3],[31118,1],[31119,3],[31121,3],[31124,3],[31125,3],[31127,3],[31304,1],[31306,3],[31307,3],[31571,3],[31573,3],[31574,3],[31576,3],[31598,1],[31601,1],[31698,1],[31701,1],[31708,1],[31789,2],[31792,1],[31797,1],[31800,3],[31862,3],[32018,3],[32019,3],[32060,1],[32252,3],[32253,3],[32258,3],[32260,11],[32263,3],[32264,3],[32265,3],[32275,11],[32276,11],[32283,1],[32293,3],[32294,3],[32299,3],[32376,1],[32378,3],[32382,1],[32384,11],[32388,3],[32393,11],[32395,11],[32404,3],[32476,1],[32478,3],[32487,3],[32706,1],[32711,11],[32729,3],[32750,1],[32763,3],[32767,3],[32768,3],[32779,3],[32783,1],[32789,2],[32790,2],[32791,2],[32794,3],[32951,3],[32954,3],[32955,3],[32956,3],[33051,3],[33053,5],[33055,3],[33056,3],[33153,3],[33154,3],[33207,3],[33244,1],[33274,3],[33275,3],[33278,3],[33320,1],[33321,1],[33331,1],[33373,3],[33376,3],[33396,1],[33401,5],[33408,5],[33409,5],[33412,1],[33433,1],[33434,1],[33436,3],[33446,1],[33453,3],[33459,3],[33460,3],[33490,1],[33492,1],[33496,2],[33499,2],[33591,1],[33595,3],[33749,3],[33750,3],[33751,2],[33752,2],[34111,3],[34710,3],[34713,3],[34810,3],[34839,1],[34903,2],[34941,3],[35362,3],[35491,1],[35493,3],[35496,3],[35498,3],[35500,3],[35681,1],[35683,1],[35684,8],[35685,7],[35686,8],[35696,3],[35752,11],[35755,3],[35756,3],[35815,1],[35873,3],[35932,2],[35935,2],[35942,3],[35943,3],[35946,1],[35951,1],[36032,3],[36033,3],[36036,1],[36037,9],[36088,5],[36095,1],[36097,3],[36101,3],[36106,3],[36108,3],[36110,1],[36111,11],[36112,11],[36121,1],[36122,3],[36124,1],[36131,3],[36358,3],[36395,5],[36397,3],[36400,11],[36401,11],[36402,11],[36411,1],[36413,1],[36414,1],[36415,1],[36499,3],[36508,1],[36516,3],[36581,3],[36582,3],[36585,11],[36592,3],[36596,2],[36605,1],[36608,1],[36744,13],[36745,3],[36792,3],[36795,1],[36797,3],[36798,1],[36828,11],[36830,3],[36831,3],[36834,1],[36985,1],[37139,11],[37150,3],[37152,3],[37154,3],[37158,23],[37162,1],[37165,1],[37166,5],[37167,5],[37168,21],[37179,1],[37180,1],[37185,3],[37188,3],[37189,3],[37190,3],[37191,3],[37192,3],[37193,3],[37207,3],[37210,11],[37212,3],[37214,1],[37216,1],[37218,3],[37224,5],[37227,2],[37232,1],[37234,3],[37237,3],[37238,3],[37256,11],[37258,3],[37264,3],[37265,3],[37344,1],[37348,1],[37364,2],[37372,11],[37377,3],[37384,11],[37386,1],[37387,1],[37388,5],[37389,1],[37391,1],[37392,3],[37393,3],[37398,3],[37481,1],[37602,3],[37605,20],[37606,3],[37677,3],[37730,2],[37737,3],[37739,3],[37740,3],[37741,3],[37742,3],[37743,3],[37744,3],[37746,3],[37748,3],[37749,3],[37753,11],[37755,5],[37763,11],[37765,2],[37775,3],[37776,3],[37779,3],[37781,1],[37789,1],[37790,12],[37791,1],[37792,3],[37793,3],[37804,3],[37809,3],[37810,3],[37813,1],[37816,3],[37818,2],[37826,3],[37834,3],[37836,3],[37838,1],[37841,2],[37843,3],[37846,11],[37847,11],[37849,1],[37855,2],[37867,11],[37868,11],[37869,11],[37875,1],[37930,1],[37931,1],[37933,3],[37941,1],[37948,11],[37951,3],[37954,1],[38007,1],[38008,1],[38009,1],[38010,1],[38011,1],[38012,1],[38014,3],[38038,1],[38040,3],[38041,3],[38042,3],[38043,3],[38044,3],[38045,3],[38046,1],[38049,1],[38070,3],[38087,3],[38091,11],[38093,3],[38098,3],[38107,3],[38109,1],[38245,3],[38248,1],[38250,11],[38251,11],[38254,3],[38256,1],[38257,1],[38331,3],[38332,3],[38337,1],[38338,1],[38339,2],[38340,2],[38342,3],[38352,3],[38354,1],[38356,3],[38358,5],[38466,3],[38528,1],[38551,3],[38552,1],[38652,3],[38707,1],[38708,1],[38710,2],[38730,3],[38733,3],[38740,3],[38741,3],[38749,3],[38752,1],[38753,1],[38755,1],[38758,1],[38759,2],[38760,2],[38764,5],[38766,2],[38771,1],[38773,1],[38775,11],[38778,3],[38779,3],[38782,1],[38833,11],[38857,11],[38858,11],[38860,2],[38861,2],[38867,3],[38908,2],[38953,11],[38977,3],[38978,3],[38991,3],[38992,3],[38995,3],[38998,2],[38999,2],[39008,3],[39011,1],[39012,1],[39013,1],[39017,3],[39019,1],[39020,3],[39022,3],[39030,1],[39034,3],[39035,3],[39057,3],[39058,3],[39059,3],[39061,1],[39062,1],[39068,2],[39070,3],[39072,3],[39073,3],[39074,3],[39075,3],[39076,3],[39077,3],[39078,3],[39079,3],[39084,1],[39086,1],[39088,21],[39089,21],[39091,2],[39120,1],[39122,3],[39127,3],[39150,1],[39155,11],[39157,3],[39159,1],[39160,1],[39163,3],[39166,11],[39168,3],[39172,3],[39177,1],[39186,1],[39188,3],[39189,3],[39190,3],[39191,3],[39197,5],[39199,23],[39202,2],[39206,3],[39208,2],[39209,2],[39210,2],[39215,7],[39216,1],[39222,3],[39227,1],[39232,1],[39233,3],[39234,3],[39237,3],[39239,1],[39240,1],[39241,1],[39249,3],[39250,3],[39251,3],[39253,5],[39256,3],[39260,1],[39265,4],[39285,3],[39358,2],[39360,3],[39375,3],[39410,1],[39416,3],[39417,29],[39418,1],[39419,1],[39420,2],[39423,1],[39425,8],[39430,2],[39440,2],[39444,3],[39451,1],[39452,1],[39453,1],[39455,1],[39460,3],[39462,1],[39467,2],[39468,3],[39472,2],[39473,2],[39474,2],[39476,3],[39481,3],[39483,3],[39484,3],[39485,3],[39487,3],[39498,3],[39500,3],[39504,3],[39508,3],[39509,3],[39522,3],[39533,11],[39574,1],[39612,3],[39613,3],[39616,3],[39617,3],[39624,2],[39634,1],[39635,23],[39650,1],[39652,1],[39727,3],[39728,3],[39731,1],[39741,11],[39751,3],[39761,3],[39762,3],[39763,3],[39766,1],[39767,1],[39768,2],[39769,1],[39770,2],[39773,3],[40001,11],[40010,1],[40011,2],[40013,1],[40014,2],[40015,2],[40018,8],[40019,8],[40020,5],[40037,3],[40039,3],[40042,2],[40043,1],[40044,2],[40045,2],[40046,2],[40053,1],[40055,2],[40056,2],[40059,1],[40061,3],[40062,3],[40063,3],[40069,1],[40070,1],[40072,1],[40075,3],[40079,3],[40080,3],[40081,3],[40082,3],[40086,3],[40087,3],[40091,3],[40100,21],[40105,11],[40107,3],[40109,1],[40110,1],[40111,1],[40115,1],[40118,1],[40119,5],[40128,11],[40129,11],[40136,2],[40137,1],[40141,3],[40143,1],[40144,13],[40146,3],[40147,3],[40208,3],[40258,3],[40261,2],[40267,1],[40269,23],[40271,3],[40272,3],[40275,1],[40277,3],[40286,2],[40294,11],[40296,3],[40298,1],[40301,1],[40305,1],[40310,1],[40315,11],[40332,3],[40333,3],[40336,1],[40338,1],[40339,1],[40340,1],[40344,1],[40345,3],[40348,3],[40349,3],[40350,3],[40351,3],[40358,1],[40360,27],[40362,1],[40364,3],[40367,1],[40374,3],[40376,1],[40380,1],[40381,1],[40384,3],[40420,1],[40424,3],[40425,3],[40482,5],[40483,5],[40484,5],[40485,5],[40505,3],[40534,11],[40536,1],[40538,1],[40544,11],[40545,11],[40547,23],[40549,11],[40552,3],[40553,3],[40554,3],[40555,2],[40613,3],[40614,3],[40617,3],[40657,2],[40663,3],[40664,3],[40697,1],[40699,1],[40701,1],[40715,1],[40716,1],[40717,1],[40718,2],[40730,11],[40732,1],[40733,3],[40746,3],[40748,11],[40749,11],[40874,3],[40875,3],[40878,1],[40880,3],[40882,3],[40887,3],[40889,11],[40890,11],[40892,2],[40894,1],[40895,3],[40899,2],[40901,2],[40902,2],[40903,3],[40904,2],[40905,2],[40906,3],[40907,3],[40908,2],[40910,3],[40911,3],[40912,2],[40914,2],[40920,3],[40921,3],[40922,3],[40925,2],[40930,5],[40931,1],[40932,1],[40933,1],[40934,1],[40935,1],[40936,3],[40938,11],[40940,3],[40941,3],[40946,3],[40958,1],[40959,1],[40960,1],[40961,1],[40964,1],[40965,2],[40966,2],[40968,12],[40970,2],[40972,2],[40973,5],[40974,9],[40975,2],[40976,5],[40977,9],[40981,1],[40982,3],[40984,3],[40988,1],[41019,11],[41021,3],[41026,1],[41028,3],[41029,3],[41032,1],[41034,3],[41036,3],[41038,1],[41103,3],[41105,1],[41121,3],[41166,2],[41167,1],[41168,2],[41169,1],[41171,2],[41173,5],[41174,11],[41175,11],[41179,3],[41182,3],[41183,3],[41184,3],[41185,3],[41186,3],[41187,3],[41188,3],[41189,3],[41191,3],[41194,1],[41238,3],[41240,1],[41241,23],[41310,3],[41328,11],[41330,11],[41334,1],[41335,1],[41380,3],[41382,3],[41384,23],[41386,1],[41394,1],[41434,11],[41456,1],[41460,1],[41464,5],[41469,23],[41471,3],[41473,1],[41549,11],[41550,11],[41552,3],[41554,11],[41556,1],[41579,4],[41581,3],[41584,1],[41586,11],[41588,3],[41589,3],[41591,3],[41592,3],[41599,1],[41601,1],[41602,4],[41603,1],[41604,1],[41605,1],[41622,3],[41634,2],[41724,3],[41725,3],[41727,1],[41729,3],[41731,5],[41744,21],[41745,21],[41747,3],[41748,3],[41752,1],[41759,1],[41770,1],[41771,1],[41772,1],[41773,1],[41774,1],[41784,2],[41785,1],[41786,1],[41787,1],[41788,2],[41789,2],[41790,1],[41793,3],[41794,3],[41836,1],[41838,2],[41841,2],[41849,2],[41850,2],[41852,2],[41853,2],[41854,2],[41855,2],[41857,1],[41859,11],[41860,11],[41861,11],[41862,11],[41866,1],[41869,3],[41871,1],[41872,1],[41873,1],[41874,1],[41875,1],[41877,1],[41879,3],[41882,1],[41884,1],[41885,1],[41886,1],[41887,1],[41888,1],[41889,1],[41890,1],[41891,1],[41893,3],[41896,5],[41898,1],[41899,1],[41900,1],[41901,1],[41903,3],[41904,3],[41907,1],[41908,1],[41911,2],[41913,2],[41914,1],[41917,3],[41918,3],[41919,3],[41920,3],[41921,3],[41922,3],[41923,3],[41924,3],[41925,3],[41926,3],[41937,1],[41940,3],[41942,3],[41944,3],[41945,3],[41948,1],[41949,1],[41954,1],[41965,1],[41966,1],[41968,1],[41972,1],[41975,1],[41977,1],[41978,1],[41988,1],[41990,1],[41991,1],[41992,1],[41993,1],[41994,1],[41995,1],[41996,1],[41997,1],[41998,1],[42000,2],[42001,1],[42009,1],[42014,1],[42015,2],[42018,1],[42019,1],[42023,1],[42026,1],[42027,1],[42028,1],[42029,1],[42031,1],[42034,1],[42041,1],[42048,1],[42058,1],[42061,12],[42063,1],[42065,1],[42070,3],[42072,1],[42075,3],[42432,3],[42662,2],[42689,2],[42691,3],[42692,3],[42695,3],[42698,3],[42709,3],[42719,1],[42738,23],[42740,3],[42741,3],[42747,3],[42749,3],[42752,1],[42753,1],[42754,1],[42755,1],[42758,5],[42759,1],[42760,1],[42761,1],[42766,2],[42767,1],[42769,2],[42771,1],[42772,1],[42773,1],[42774,1],[42775,2],[42777,2],[42778,24],[42779,1],[42780,1],[42781,1],[42782,1],[42783,2],[42785,2],[42786,2],[42792,4],[42793,1],[42795,9],[42801,3],[42803,3],[42804,3],[42805,3],[42806,3],[42807,3],[42808,3],[42809,3],[42810,3],[42811,3],[42812,3],[42814,3],[42815,3],[42818,3],[42825,1],[42826,26],[42828,1],[42829,9],[42831,18],[42835,1],[42837,1],[42838,1],[42839,1],[42840,1],[42841,1],[42842,1],[42844,2],[42845,1],[42846,1],[42847,1],[42848,1],[42849,1],[42900,1],[42901,1],[42907,3],[42915,3],[42917,23],[42920,1],[42921,9],[42922,2],[42934,3],[42939,11],[42941,1],[42942,3],[42945,1],[42946,1],[42947,1],[42949,3],[42950,3],[42951,3],[42954,1],[42955,3],[42956,3],[42957,3],[42958,3],[42959,3],[42960,3],[42961,3],[42962,3],[42963,3],[42964,3],[42965,23],[42967,3],[42969,1],[42982,12],[42984,3],[42987,1],[42988,1],[42989,1],[42990,1],[42991,1],[42992,1],[42997,1],[43001,11],[43002,11],[43005,1],[43010,1],[43011,1],[43013,1],[43014,2],[43017,2],[43022,1],[43023,1],[43024,1],[43028,1],[43029,1],[43030,1],[43032,1],[43034,1],[43039,3],[43041,1],[43045,1],[43047,1],[43048,1],[43050,2],[43051,1],[43053,1],[43054,1],[43055,11],[43056,11],[43057,11],[43058,11],[43065,1],[43070,3],[43071,3],[43072,3],[43073,3],[43074,3],[43075,3],[43076,3],[43077,3],[43078,3],[43079,3],[43080,1],[43081,1],[43082,1],[43083,1],[43099,1],[43100,1],[43107,11],[43108,11],[43111,1],[43113,3],[43114,1],[43115,2],[43116,2],[43118,1],[43123,1],[43124,1],[43125,1],[43126,1],[43127,2],[43130,2],[43131,1],[43143,1],[43144,9],[43145,1],[43146,1],[43152,1],[43155,2],[43156,2],[43157,3],[43158,2],[43159,1],[43160,1],[43162,1],[43165,1],[43167,1],[43169,2],[43170,1],[43171,1],[43172,1],[43174,3],[43175,3],[43178,3],[43180,1],[43181,1],[43182,1],[43183,1],[43184,1],[43185,1],[43186,2],[43187,2],[43188,2],[43189,2],[43192,2],[43194,4],[43195,1],[43196,2],[43197,1],[43199,2],[43204,1],[43207,11],[43208,11],[43215,1],[43223,1],[43226,1],[43228,3],[43231,3],[43232,3],[43233,3],[43234,3],[43236,1],[43245,11],[43246,11],[43249,3],[43250,3],[43251,3],[43252,3],[43253,3],[43254,3],[43255,3],[43256,3],[43257,3],[43258,3],[43259,1],[43260,1],[43262,1],[43271,3],[43272,3],[43275,1],[43276,1],[43277,1],[43279,2],[43286,23],[43339,3],[43432,3],[43435,5],[43437,1],[43439,1],[43440,1],[43441,1],[43442,1],[43443,1],[43446,2],[43450,3],[43461,1],[43463,3],[43476,1],[43477,1],[43478,3],[43479,3],[43480,3],[43481,3],[43482,3],[43484,1],[43485,1],[43488,3],[43491,1],[43495,1],[43508,11],[43518,2],[43519,2],[43529,1],[43530,1],[43539,11],[43547,5],[43556,2],[43557,2],[43558,1],[43559,1],[43560,1],[43561,1],[43562,3],[43564,11],[43565,11],[43566,11],[43567,11],[43569,3],[43570,3],[43571,3],[43572,3],[43573,3],[43574,3],[43575,3],[43576,3],[43577,3],[43578,3],[43581,11],[43582,11],[43585,1],[43587,3],[43600,1],[43602,11],[43603,11],[43609,1],[43611,3],[43613,4],[43616,5],[43618,1],[43619,1],[43622,11],[43623,11],[43632,3],[43633,3],[43636,2],[43641,1],[43642,1],[43647,11],[43648,11],[43651,3],[43655,1],[43656,3],[43657,1],[43662,1],[43668,3],[43669,2],[43672,1],[43676,1],[43677,5],[43678,1],[43683,11],[43687,11],[43689,1],[43690,1],[43694,2],[43695,1],[43696,2],[43697,1],[43698,3],[43700,3],[43706,11],[43707,11],[43710,5],[43712,2],[43713,3],[43717,1],[43719,1],[43720,3],[43721,1],[43722,2],[43723,1],[43724,1],[43725,1],[43729,3],[43730,1],[43731,1],[43732,1],[43733,1],[43737,1],[43738,2],[43741,1],[43742,1],[43743,1],[43744,2],[43745,1],[43746,1],[43747,1],[43751,3],[43752,3],[43753,3],[43759,3],[43764,3],[43765,22],[43767,1],[43768,1],[43769,1],[43770,3],[43772,2],[43773,2],[43774,2],[43775,3],[43780,2],[43783,1],[43785,2],[43790,1],[43792,16],[43793,5],[43794,22],[43795,2],[43796,2],[43797,1],[43799,22],[43800,1],[43802,1],[43803,3],[43804,2],[43805,2],[43807,2],[43808,3],[43809,3],[43811,5],[43812,1],[43813,2],[43815,2],[43816,3],[43817,3],[43818,3],[43819,2],[43820,1],[43822,1],[43823,1],[43824,3],[43831,1],[43833,1],[43836,2],[43837,2],[43838,2],[43839,2],[43840,2],[43841,2],[43842,2],[43849,2],[43850,2],[43853,5],[43855,2],[43856,5],[43857,15],[43858,2],[43860,5],[43861,2],[43864,3],[43866,1],[43867,3],[43871,2],[43873,11],[43874,2],[43876,1],[43877,1],[43879,3],[43880,29],[43881,2],[43882,1],[43883,1],[43884,1],[43885,1],[43886,1],[43887,1],[43888,1],[43889,1],[43890,1],[43893,1],[43899,1],[43902,1],[43905,1],[43906,1],[43907,1],[43908,3],[43909,1],[43910,1],[43911,1],[43912,1],[43913,1],[43914,3],[43915,1],[43917,2],[43920,3],[43922,3],[43923,3],[43924,3],[43925,3],[43926,3],[43927,3],[43928,3],[43929,3],[43930,3],[43931,3],[43932,2],[43934,1],[43935,1],[43937,3],[43941,1],[43942,1],[43943,1],[43944,2],[43946,1],[44034,3],[44035,3],[44047,1],[44048,3],[44057,3],[44058,3],[44059,3],[44060,3],[44061,3],[44062,3],[44067,3],[44071,3],[44072,1],[44076,3],[44078,1],[44080,1],[44084,1],[44085,1],[44086,1],[44087,1],[44088,1],[44090,1],[44095,1],[44098,1],[44103,1],[44105,2],[44109,2],[44112,3],[44113,3],[44114,3],[44115,3],[44186,3],[44204,11],[44207,1],[44209,1],[44226,2],[44229,2],[44231,11],[44233,1],[44299,11],[44307,3],[44310,1],[44311,3],[44312,1],[44313,2],[44314,1],[44315,2],[44316,2],[44322,1],[44323,1],[44324,1],[44333,3],[44334,3],[44337,11],[44339,2],[44340,2],[44341,2],[44343,1],[44344,2],[44347,2],[44349,1],[44350,1],[44351,1],[44353,1],[44354,2],[44356,2],[44358,1],[44360,2],[44365,1],[44367,1],[44387,1],[44388,2],[44389,1],[44390,1],[44391,2],[44392,5],[44394,5],[44396,1],[44399,2],[44400,2],[44402,1],[44403,1],[44404,5],[44405,1],[44406,2],[44407,1],[44408,2],[44409,1],[44411,1],[44412,2],[44414,1],[44415,2],[44419,3],[44421,2],[44422,2],[44423,2],[44424,2],[44449,1],[44450,1],[44451,1],[44453,3],[44457,3],[44475,3],[44476,3],[44479,3],[44481,3],[44482,2],[44486,1],[44487,3],[44488,1],[44495,1],[44497,2],[44498,2],[44499,1],[44506,11],[44517,4],[44519,2],[44520,5],[44528,1],[44529,1],[44534,1],[44536,1],[44537,1],[44538,1],[44539,1],[44542,11],[44543,11],[44552,1],[44622,1],[44624,3],[44625,25],[44628,5],[44634,9],[44637,2],[44703,1],[44704,1],[44705,3],[44706,2],[44709,11],[44777,1],[44779,1],[44780,1],[44781,1],[44782,1],[44783,1],[44785,2],[44786,2],[44793,11],[44794,11],[44797,14],[44800,3],[44801,3],[44804,1],[44806,2],[44808,1],[44809,1],[44811,1],[44812,1],[44814,1],[44816,1],[44818,1],[44819,1],[44824,4],[44835,14],[44836,1],[44838,1],[44839,1],[44840,3],[44841,3],[44842,2],[44843,2],[44850,11],[44852,2],[44853,2],[44855,1],[44856,1],[44857,1],[44859,1],[44860,1],[44861,1],[44863,1],[44864,11],[44865,11],[44868,3],[44873,1],[44874,5],[44876,3],[44877,5],[44879,1],[44880,1],[44881,2],[44883,1],[44903,1],[44905,3],[44906,3],[44907,3],[44910,2],[44978,3],[45016,1],[45017,1],[45018,1],[45019,3],[45024,3],[45026,3],[45027,3],[45110,2],[45114,2],[45116,2],[45117,2],[45121,2],[45125,2],[45131,3],[45132,3],[45133,3],[45134,3],[45135,3],[45136,3],[45137,3],[45138,3],[45139,3],[45140,3],[45141,3],[45142,3],[45143,3],[45144,3],[45145,3],[45146,3],[45147,3],[45148,3],[45149,3],[45150,3],[45151,3],[45152,3],[45153,3],[45154,3],[45155,3],[45156,3],[45157,3],[45158,3],[45159,3],[45160,3],[45161,3],[45162,3],[45163,3],[45164,3],[45165,1],[45245,3],[45246,1],[45249,2],[45250,2],[45251,2],[45253,2],[45254,3],[45263,5],[45264,5],[45344,11],[45358,11],[45424,3],[45425,3],[45426,3],[45427,3],[45428,3],[45429,3],[45430,3],[45431,3],[45432,3],[45433,3],[45434,3],[45435,3],[45436,3],[45437,3],[45438,3],[45439,3],[45440,3],[45441,3],[45442,3],[45443,3],[45444,3],[45445,3],[45446,3],[45447,3],[45448,3],[45449,3],[45450,3],[45451,3],[45452,3],[45453,3],[45454,3],[45455,3],[45456,3],[45457,3],[45460,1],[45461,1],[45462,1],[45465,3],[45602,3],[45603,3],[45605,3],[45606,2],[45608,1],[45610,2],[45611,2],[45612,2],[45624,1],[45625,1],[45721,1],[45723,10],[45724,10],[45725,10],[45726,6],[45727,2],[45788,1],[45789,1],[45790,1],[45794,1],[45795,2],[45796,1],[45807,11],[45854,11],[45856,1],[45859,5],[45860,1],[45863,3],[45873,1],[45874,1],[45875,1],[45876,1],[45916,2],[45920,3],[45939,1],[45941,2],[45985,3],[45986,3],[46025,1],[46026,4],[46088,1],[46089,1],[46112,3],[46113,25],[46114,3],[46179,1],[46180,1],[46200,22],[46232,1],[46233,2],[46234,2],[46235,1],[46265,1],[46266,4],[46267,9],[46272,1],[46273,1],[46274,9],[46275,3],[46276,2],[46277,1],[46278,4],[46279,4],[46280,2],[46281,2],[46284,5],[46285,1],[46286,1],[46288,1],[46289,1],[46290,1],[46291,1],[46292,1],[46293,1],[46294,2],[46295,2],[46296,1],[46297,1],[46298,1],[46299,1],[46312,1],[46313,1],[46314,1],[46315,1],[46316,1],[46317,1],[46318,1],[46319,3],[46320,1],[46396,1],[46454,1],[46455,1],[46456,1],[46457,1],[46458,1],[46459,1],[46460,1],[46461,1],[46462,1],[46469,1],[46478,1],[46479,1],[46486,3],[46487,3],[46488,3],[46489,1],[46490,5],[46491,5],[46492,3],[46493,5],[46494,5],[46495,5],[46496,1],[46497,1],[46498,3],[46499,3],[46500,1],[46501,1],[46502,1],[46503,1],[46504,9],[46505,9],[46506,9],[46507,9],[46527,1],[46528,1],[46529,1],[46597,1],[46609,1],[46610,1],[46621,1],[46735,1],[46737,1],[46738,1],[46805,11],[46807,1],[46808,1],[46809,1],[46810,2],[46812,1],[46813,1],[46814,1],[46815,1],[46816,1],[46817,1],[46818,9],[46819,1],[46820,1],[46821,1],[46822,1],[46825,1],[46826,11],[46827,1],[46828,1],[46829,1],[46830,1],[46831,1],[46832,1],[46833,1],[46835,1],[46836,1],[46840,1],[46904,2],[46905,1],[46906,1],[46907,1],[46908,1],[46909,1],[46910,1],[46911,1],[46912,1],[46914,1],[46916,3],[46918,1],[46926,1],[46931,1],[46941,1],[46943,1],[46984,1],[47202,3],[47226,1],[47227,3],[47228,3],[47229,3],[47230,2],[47231,1],[47234,5],[47235,5],[47237,1],[47253,1],[47256,3],[47258,3],[47259,3],[47260,3],[47261,3],[47262,3],[47263,3],[47264,3],[47265,3],[47266,3],[47267,3],[47268,3],[47269,3],[47270,3],[47271,3],[47272,3],[47273,3],[47274,3],[47275,3],[47276,3],[47277,3],[47278,3],[47279,3],[47280,3],[47281,3],[47282,3],[47283,3],[47284,3],[47285,3],[47286,3],[47287,3],[47288,3],[47289,3],[47290,3],[47291,3],[47292,3],[47293,3],[47294,10],[47295,10],[47296,2],[47297,1],[47298,9],[47299,2],[47300,1],[47302,1],[47305,1],[47306,3],[47309,2],[47310,1],[47317,2],[47318,2],[47319,5],[47320,2],[47321,3],[47346,3],[47429,3],[47430,3],[47438,9],[47440,3],[47441,1],[47445,5],[47446,3],[47448,2],[47450,1],[47452,1],[47453,1],[47454,3],[47456,1],[47457,1],[47459,3],[47461,3],[47462,1],[47463,9],[47465,3],[47467,2],[47469,1],[47471,1],[47472,1],[47473,1],[47474,1],[47475,1],[47476,3],[47477,1],[47478,1],[47483,9],[47484,2],[47485,1],[47486,3],[47487,3],[47488,3],[47490,1],[47491,1],[47492,1],[47493,1],[47494,1],[47495,1],[47496,1],[47498,1],[47500,1],[47501,3],[47502,22],[47503,3],[47505,22],[47506,1],[47507,1],[47508,22],[47509,4],[47510,1],[47511,1],[47514,1],[47515,1],[47516,1],[47517,3],[47518,1],[47519,3],[47521,1],[47522,1],[47523,1],[47524,9],[47525,1],[47526,2],[47527,1],[47528,1],[47529,1],[47530,1],[47531,3],[47532,1],[47533,1],[47536,1],[47538,1],[47539,1],[47540,1],[47541,2],[47542,1],[47543,1],[47544,1],[47545,1],[47546,1],[47612,1],[47613,3],[47615,2],[47616,2],[47617,1],[47684,1],[47685,1],[47686,1],[47687,1],[47688,1],[47691,1],[47693,1],[47695,1],[47698,1],[47699,1],[47701,2],[47719,1],[47851,2],[47854,1],[47856,1],[47857,1],[47932,1],[47933,1],[47934,1],[47935,1],[47936,1],[47937,2],[47938,5],[47939,2],[47940,1],[47941,3],[47942,2],[47943,2],[47944,2],[47948,3],[47949,3],[47950,5],[47953,1],[47954,2],[47955,3],[47956,2],[47957,9],[47961,3],[47965,1],[47966,9],[47967,2],[47968,9],[47969,1],[47971,1],[47972,2],[48042,3],[48043,3],[48044,3],[48045,3],[48046,3],[48047,3],[48048,3],[48049,3],[48050,3],[48051,3],[48052,3],[48053,3],[48054,3],[48055,3],[48056,3],[48057,3],[48058,3],[48059,3],[48060,3],[48061,3],[48062,3],[48063,3],[48064,3],[48065,3],[48066,3],[48067,3],[48068,3],[48069,3],[48070,3],[48071,3],[48072,3],[48073,3],[48074,3],[48075,3],[48076,3],[48077,3],[48079,1],[48083,9],[48084,9],[48085,9],[48157,2],[48210,3],[48211,3],[48212,3],[48213,3],[48214,3],[48215,3],[48216,3],[48217,3],[48218,3],[48219,3],[48220,3],[48221,3],[48222,3],[48223,3],[48224,3],[48225,3],[48226,3],[48227,3],[48228,3],[48229,3],[48230,3],[48231,3],[48232,3],[48233,3],[48234,3],[48235,3],[48236,3],[48237,3],[48238,3],[48239,3],[48240,3],[48241,3],[48242,3],[48243,3],[48244,3],[48245,3],[48247,1],[48248,1],[48249,1],[48250,2],[48251,2],[48252,2],[48253,2],[48254,1],[48255,1],[48256,2],[48261,1],[48268,1],[48269,1],[48270,3],[48271,9],[48272,1],[48273,1],[48275,5],[48340,1],[48423,1],[48424,1],[48425,1],[48426,2],[48605,1],[48606,2],[48618,1],[48767,3],[48768,3],[48769,3],[48770,3],[48771,3],[48772,3],[48773,3],[48774,3],[48775,3],[48776,3],[48777,3],[48778,3],[48779,3],[48780,3],[48781,3],[48782,3],[48783,3],[48784,3],[48785,3],[48786,3],[48787,3],[48788,3],[48789,3],[48790,3],[48791,3],[48792,3],[48793,3],[48794,3],[48795,3],[48796,3],[48797,3],[48798,3],[48799,3],[48800,3],[48801,3],[48802,3],[48808,1],[48838,3],[48840,1],[48841,5],[48842,1],[48844,21],[48846,2],[48847,2],[48848,2],[48850,1],[48859,11],[48860,1],[48861,1],[48863,1],[48864,2],[48865,1],[48872,1],[48873,1],[48874,3],[48875,3],[48876,1],[48877,3],[48878,1],[48882,3],[48883,3],[48884,3],[48885,1],[48886,3],[48887,3],[48888,3],[48889,3],[48890,3],[48891,3],[48892,9],[48893,3],[48894,3],[48895,3],[48896,3],[48897,3],[48898,9],[48899,3],[48900,9],[48901,1],[48902,3],[48903,3],[48904,3],[48905,1],[48906,1],[48907,2],[48909,9],[48910,4],[48911,30],[48914,1],[48915,3],[48916,1],[48917,1],[48918,1],[48919,1],[48920,1],[48921,1],[48922,1],[48923,1],[48924,17],[48925,1],[48926,1],[48927,1],[48928,1],[48929,1],[48930,1],[48931,22],[48938,3],[48942,1],[48943,3],[48948,22],[48950,1],[48951,2],[48952,3],[48953,1],[48954,3],[48955,3],[48957,22],[48959,1],[48960,3],[48961,3],[48962,1],[48963,1],[48964,2],[48965,2],[48966,1],[48967,3],[48968,3],[48970,3],[48971,3],[48972,3],[48973,3],[48974,3],[48975,3],[48976,3],[48977,3],[48978,3],[48979,3],[48980,3],[48981,3],[48982,3],[48984,3],[48985,3],[48986,3],[48987,3],[48988,3],[48989,3],[48990,3],[48991,3],[48992,3],[48993,3],[48994,3],[48995,3],[48996,3],[48997,3],[48998,3],[48999,3],[49000,3],[49001,3],[49002,3],[49003,1],[49004,1],[49005,1],[49006,1],[49007,1],[49008,1],[49011,3],[49013,2],[49014,1],[49015,2],[49016,2],[49018,1],[49019,1],[49020,1],[49021,1],[49022,1],[49026,1],[49027,2],[49028,1],[49029,1],[49049,1],[49052,2],[49055,3],[49056,3],[49059,2],[49060,2],[49062,3],[49066,1],[49067,9],[49068,5],[49069,2],[49070,1],[49071,1],[49072,1],[49075,3],[49076,3],[49077,3],[49078,3],[49079,3],[49080,3],[49081,3],[49082,3],[49083,3],[49084,3],[49085,3],[49086,3],[49087,3],[49088,3],[49089,3],[49090,3],[49091,3],[49092,3],[49093,3],[49094,3],[49095,3],[49096,3],[49097,3],[49098,3],[49099,3],[49100,3],[49101,3],[49102,3],[49103,3],[49104,3],[49105,3],[49106,3],[49107,3],[49108,3],[49112,3],[49114,3],[49115,3],[49122,1],[49125,3],[49186,3],[49187,3],[49188,3],[49189,3],[49190,3],[49191,3],[49192,3],[49193,3],[49194,3],[49195,3],[49196,3],[49197,3],[49198,3],[49199,3],[49200,3],[49201,3],[49202,3],[49203,3],[49204,3],[49205,3],[49206,3],[49207,3],[49208,3],[49209,3],[49210,3],[49211,3],[49212,3],[49213,3],[49214,3],[49215,3],[49216,3],[49217,3],[49218,3],[49219,3],[49256,1],[49260,1],[49261,2],[49262,2],[49263,5],[49264,4],[49279,3],[49280,3],[49281,3],[49282,3],[49283,3],[49284,3],[49285,3],[49286,3],[49287,3],[49288,3],[49289,3],[49290,3],[49291,3],[49292,3],[49293,3],[49294,3],[49295,3],[49296,3],[49297,3],[49298,3],[49299,3],[49300,3],[49301,3],[49302,3],[49303,3],[49304,3],[49305,3],[49306,3],[49307,3],[49308,3],[49309,3],[49310,3],[49311,3],[49312,3],[49313,3],[49314,3],[49315,5],[49317,2],[49319,1],[49321,2],[49322,1],[49323,9],[49324,1],[49325,2],[49330,2],[49332,3],[49333,3],[49336,23],[49338,1],[49383,1],[49384,1],[49387,1],[49390,1],[49391,1],[49392,1],[49395,9],[49396,2],[49397,2],[49398,9],[49399,2],[49400,9],[49402,2],[49403,2],[49464,1],[49465,1],[49466,1],[49469,1],[49470,1],[49492,1],[49495,1],[49501,2],[49503,1],[49505,3],[49809,11],[49810,11],[49812,1],[49813,2],[49814,10],[49815,1],[49816,1],[49817,9],[49818,2],[49949,1],[49950,1],[49954,5],[49961,1],[49962,1],[50001,3],[50002,3],[50005,3],[50212,3],[50319,3],[50321,2],[50322,2],[50469,3],[50470,3],[50471,3],[50472,3],[50473,3],[50474,3],[50475,3],[50476,3],[50477,3],[50478,3],[50479,3],[50480,3],[50481,3],[50482,3],[50483,3],[50484,3],[50485,3],[50486,3],[50487,3],[50488,3],[50489,3],[50490,3],[50491,3],[50492,3],[50493,3],[50494,3],[50495,3],[50496,3],[50497,3],[50498,3],[50499,3],[50500,3],[50501,3],[50502,3],[50503,3],[50504,3],[50986,1],[50992,1],[50993,1],[50995,1],[50996,1],[50997,1],[50998,3],[50999,1],[51000,1],[51002,3],[51003,1],[51004,1],[51005,1],[51006,1],[51007,1],[51008,1],[51009,1],[51010,1],[51011,1],[51013,2],[51014,2],[51015,1],[51016,1],[51017,1],[51018,1],[51019,3],[51020,1],[51021,1],[51022,1],[51023,1],[51024,1],[51026,1],[51027,1],[51028,1],[51029,1],[51030,1],[51031,3],[51032,2],[51033,3],[51035,1],[51036,1],[51037,1],[51038,1],[51039,1],[51040,1],[51041,1],[51042,1],[51043,1],[51045,1],[51046,1],[51047,1],[51048,1],[51049,1],[51050,1],[51051,3],[51052,1],[51054,1],[51056,1],[51057,3],[51058,1],[51059,3],[51062,3],[51063,3],[51064,1],[51065,1],[51066,1],[51068,3],[51069,2],[51070,1],[51071,1],[51072,1],[51073,3],[51075,2],[51077,2],[51082,2],[51083,3],[51084,2],[51087,1],[51088,1],[51094,2],[51095,2],[51096,2],[51097,3],[51098,1],[51099,2],[51102,2],[51280,21],[51281,21],[51284,1],[51444,1],[51445,1],[51511,1],[51622,3],[51623,3],[51624,3],[51625,3],[51626,3],[51627,3],[51628,3],[51629,3],[51630,3],[51631,3],[51632,3],[51633,3],[51634,3],[51635,3],[51636,3],[51637,3],[51638,3],[51639,3],[51640,3],[51641,3],[51642,3],[51643,3],[51644,3],[51645,3],[51646,3],[51647,3],[51648,3],[51649,3],[51650,3],[51651,3],[51652,3],[51653,3],[51654,3],[51655,3],[51656,1],[51657,4],[51658,1],[51822,1],[51824,2],[51825,1],[51826,1],[51827,1],[51828,1],[51829,1],[51830,1],[51831,1],[51832,1],[51833,1],[51834,1],[51835,1],[51836,1],[51837,1],[51838,1],[51839,1],[51840,1],[51841,1],[51843,1],[51845,1],[51846,1],[51847,1],[51850,1],[51946,3],[51947,3],[51948,3],[51949,3],[51950,3],[51951,3],[51954,1],[52009,3],[52010,3],[52011,3],[52012,3],[52013,3],[52014,3],[52015,3],[52016,3],[52017,2],[52018,3],[52019,3],[52020,3],[52021,3],[52022,3],[52023,3],[52024,3],[52025,3],[52026,3],[52027,3],[52028,3],[52029,3],[52084,1],[52146,3],[52150,2],[52151,1],[52157,3],[52158,4],[52159,1],[52160,2],[52161,9],[52162,3],[52164,3],[52165,22],[52166,3],[52167,22],[52168,1],[52170,22],[52171,1],[52172,1],[52174,1],[52175,9],[52176,3],[52177,3],[52178,1],[52179,3],[52180,3],[52181,3],[52182,3],[52183,3],[52184,1],[52185,3],[52186,3],[52187,3],[52188,2],[52189,1],[52190,1],[52191,4],[52192,4],[52193,1],[52194,1],[52196,1],[52197,1],[52200,1],[52202,1],[52255,3],[52257,4],[52259,1],[52320,1],[52322,1],[52388,1],[52389,1],[52390,1],[52391,1],[52392,1],[52394,3],[52395,3],[52396,3],[52397,3],[52398,3],[52399,3],[52400,3],[52401,3],[52402,3],[52403,3],[52404,3],[52405,3],[52406,3],[52407,3],[52408,3],[52409,3],[52410,3],[52411,3],[52412,3],[52413,3],[52414,3],[52415,3],[52416,3],[52417,3],[52418,2],[52419,2],[52420,2],[52422,1],[52423,2],[52424,2],[52426,2],[52443,1],[52444,1],[52445,1],[52446,1],[52447,1],[52448,1],[52449,1],[52450,1],[52713,1],[52732,1],[52733,1],[52735,1],[52736,1],[52741,1],[52747,1],[52748,1],[52749,1],[52752,1],[52755,1],[52758,1],[52759,1],[52762,1],[52764,1],[52769,1],[52785,19],[52786,19],[52787,19],[52788,19],[52789,19],[52790,19],[52791,19],[52792,19],[52793,19],[52817,3],[52887,1],[52888,3],[52889,10],[52890,10],[52891,10],[52892,10],[52894,9],[52897,1],[52898,1],[52899,9],[52901,5],[52903,3],[52904,3],[52907,1],[52908,1],[52909,1],[52912,1],[52933,3],[52935,1],[52937,1],[52941,2],[52942,2],[52984,11],[53100,3],[53102,1],[53128,1],[53129,1],[53316,1],[53318,1],[53352,2],[53355,1],[53370,1],[53371,2],[53372,2],[53586,2],[53698,1],[53757,3],[53758,3],[53760,1],[53761,1],[53763,1],[53765,3],[53808,3],[53813,3],[53815,1],[53876,2],[53877,1],[53883,1],[53884,2],[53885,2],[53943,1],[53946,1],[53947,1],[53948,2],[53949,2],[53950,2],[53960,3],[53961,3],[54020,2],[54021,2],[54026,3],[54027,3],[54029,5],[54031,11],[54033,3],[54035,1],[54042,1],[54043,1],[54045,1],[54048,3],[54109,22],[54110,22],[54113,3],[54114,3],[54115,3],[54116,3],[54117,3],[54118,3],[54119,3],[54120,3],[54121,3],[54122,3],[54123,3],[54124,3],[54125,3],[54126,3],[54127,3],[54128,3],[54129,3],[54130,3],[54131,3],[54132,3],[54133,3],[54134,3],[54135,3],[54136,3],[54137,3],[54138,3],[54139,3],[54140,3],[54141,3],[54142,3],[54143,3],[54144,3],[54145,3],[54146,3],[54147,3],[54148,3],[54225,3],[54642,3],[54643,3],[54644,3],[54645,3],[54646,3],[54647,3],[54648,3],[54649,3],[54650,3],[54651,3],[54652,3],[54653,3],[54654,3],[54655,3],[54656,3],[54657,3],[54658,3],[54659,3],[54660,3],[54661,3],[54662,3],[54663,3],[54664,3],[54665,3],[54666,3],[54667,3],[54668,3],[54669,3],[54670,3],[54671,3],[54672,3],[54673,3],[54674,3],[54675,3],[54676,3],[54677,3],[54678,3],[54679,3],[54680,3],[54681,3],[54940,5],[55009,9],[55010,1],[55011,1],[55012,3],[55013,1],[55014,1],[55015,1],[55017,1],[55018,1],[55019,1],[55020,1],[55021,1],[55022,1],[55023,1],[55024,1],[55025,1],[55026,1],[55027,1],[55028,1],[55029,1],[55030,1],[55031,1],[55032,1],[55033,1],[55034,3],[55035,1],[55036,1],[55037,1],[55038,1],[55039,1],[55040,1],[55041,9],[55042,1],[55043,1],[55044,1],[55045,1],[55046,3],[55047,1],[55048,1],[55049,1],[55050,1],[55052,9],[55053,1],[55054,9],[55055,1],[55056,2],[55057,1],[55058,9],[55061,9],[55062,1],[55063,1],[55064,1],[55065,1],[55066,1],[55067,2],[55068,1],[55069,1],[55070,1],[55071,1],[55072,5],[55073,5],[55074,1],[55075,1],[55076,9],[55077,1],[55078,1],[55079,1],[55080,1],[55081,2],[55082,1],[55083,1],[55084,2],[55085,1],[55086,1],[55087,3],[55088,1],[55089,3],[55090,9],[55091,3],[55092,3],[55093,1],[55094,3],[55095,3],[55096,3],[55097,3],[55098,3],[55099,3],[55100,3],[55101,3],[55102,3],[55103,2],[55107,1],[55108,2],[55133,2],[55134,28],[55135,28],[55136,2],[55137,2],[55138,2],[55140,3],[55141,3],[55142,3],[55143,3],[55144,3],[55145,3],[55146,3],[55147,3],[55148,3],[55149,3],[55150,3],[55151,3],[55152,3],[55153,3],[55154,3],[55155,3],[55156,3],[55157,3],[55158,3],[55159,3],[55160,3],[55161,3],[55162,3],[55163,3],[55164,3],[55165,3],[55166,3],[55167,3],[55168,3],[55169,3],[55239,3],[55242,2],[55243,2],[55244,1],[55248,1],[55249,1],[55250,1],[55251,1],[55252,1],[55253,1],[55254,1],[55255,1],[55256,1],[55257,1],[55258,1],[55259,1],[55260,1],[55261,2],[55263,3],[55264,2],[55268,11],[55324,22],[55326,22],[55327,22],[55329,1],[55506,1],[55508,3],[55562,9],[55683,3],[55686,3],[55690,1],[55801,3],[55802,3],[55803,3],[55804,3],[55805,3],[55806,3],[55807,3],[55808,3],[55809,3],[55810,3],[55811,3],[55812,3],[55813,3],[55814,3],[55815,3],[55816,3],[55817,3],[55818,3],[55819,3],[55820,3],[55821,3],[55822,3],[55823,3],[55824,3],[55825,3],[55826,3],[55827,3],[55828,3],[55829,3],[55830,3],[55836,1],[55839,1],[55841,3],[55844,1],[55861,2],[55909,1],[55910,1],[55912,1],[55970,3],[55971,3],[55973,28],[55974,28],[55975,28],[55976,28],[55978,1],[55982,1],[55983,1],[56055,3],[56056,3],[56057,3],[56058,3],[56059,3],[56060,3],[56061,3],[56062,3],[56063,3],[56064,3],[56065,3],[56066,3],[56067,3],[56068,3],[56069,3],[56070,3],[56071,3],[56072,3],[56073,3],[56074,3],[56075,3],[56076,3],[56077,3],[56078,3],[56079,3],[56080,3],[56081,3],[56083,1],[56091,14],[56153,1],[56154,1],[56155,1],[56156,1],[56157,1],[56162,9],[56163,9],[56164,9],[56165,9],[56166,9],[56167,9],[56168,9],[56169,9],[56170,9],[56171,9],[56174,3],[56178,1],[56179,2],[56180,1],[56181,3],[56182,1],[56183,3],[56184,2],[56185,1],[56186,4],[56187,4],[56188,5],[56189,2],[56190,1],[56191,22],[56193,22],[56194,1],[56195,1],[56196,2],[56197,1],[56198,1],[56199,2],[56201,1],[56202,1],[56203,1],[56204,4],[56205,1],[56206,1],[56207,1],[56208,2],[56209,4],[56210,1],[56211,14],[56212,2],[56213,1],[56214,3],[56215,9],[56216,9],[56217,3],[56218,3],[56219,4],[56220,4],[56221,5],[56222,5],[56223,9]]} +{"meta":{"source":"Union of Concerned Scientists Satellite Database","version":"UCS-Satellite-Database 5-1-2023","url":"https://www.ucsusa.org/satellite_database","dataCurrentTo":"2023-05-01","license":"Free, unrestricted use; acknowledgement requested (UCS database manual, section 3)","curation":{"sourceRows":7560,"starlinkRowsDropped":3996,"invalidNoradDropped":0,"duplicateNoradDropped":0,"columns":{"operator":"Operator/Owner","operatorCountry":"Country of Operator/Owner","purpose":"Purpose","detailedPurpose":"Detailed Purpose","users":"Users","orbitClass":"Class of Orbit"}},"recordCount":3564},"fields":["noradId","operator","operatorCountry","purpose","detailedPurpose","users","orbitClass"],"strings":{"operator":["","Hera Systems","AAC Clyde Space","Aalto University","University of Aalborg","Asia Broadcast Satellite Ltd.","Asher Space Research Institute at Technion/Israeli Aircraft Industries","Austrian Space Forum (OEWF)/Spire","National Reconnaissance Office (NRO)","US Air Force","Department of Homeland Security","European Space Agency (ESA)","Aerospace Corporation","EUTELSAT S.A.","Aurora Insight","Center for Atmospheric Sciences, Hampton University/NASA","Norwegian Coastal Admnistration","AISTech","Al Yah Satellite Communications Co. (YAHSAT)","Al-Farabi Kazakh National University","Algerian Space Agency (ASAL)","Astro Live Experiences","University of Brasilia","US Air Force Institute of Technology","Algerian Space Agency (ASAL)/UK Space Agency","Hispamar (subsidiary of Hispasat - Spain)","National Institute for Space Research (INPE)","SES S.A.","Moscow State University","Space-Communication Ltd.","AMSAT-NA","Agency for Defense Development","ANDESITE - Boston University","Centre National d'Etudes Spatiales (CNES)","AngoSat","Telesat Canada Ltd. (BCE, Inc.)","Aprize Satellite, Argentina","APT Satellite Holdings Ltd.","Arab Satellite Communications Org. (ASCO)","University of South Florida, Institute of Applied Engineering (IAE).","Norwegian Defence Research Establishment","Aoyama Gakuin University in Tokyo","Naval Physical and Oceanographic Laboratory","Planetary Resources","ArSat","Aerospacelab","Istanbul Technical University","Asia Satellite Telecommunications Co. Ltd.","1Worldspace","Japan Space Systems","Chiba Institute of Technology","Astranis","Astrocast","Telemetry Tracking and Command Network (ISTRAC) Centre","DirecTV, Inc.","PointView Tech","Centre National d'Etudes Spatiales (CNES)/Agenzia Spaziale Italiana (ASI)","Microspace Rapid Pvt Ltd.","Azercosmos","Bangladesh Telecommunication Regulatory Commission (BTRC)","Tianyi Research Institute","Ministry of Defense","Space Development Agency","Central European Institute of Technology","Technical University Berlin","Chinese Ministry of National Defense","21st Century Aerospace Technology (21AT)","Beijing Landview Mapping Information Technology Co. Ltd (BLMIT)","Changsha Tianyi space science and Technology Research Institute Co., Ltd. (Spacety)","Belintersat","Institute of Space Sensor Technology and Planetary Exploration","Norwegian Defence Research Establishment (FFI)/","German Aerospace Center (DLR)","Salish Kootenai College","National Academy of Sciences","BlackSky Global","NanoAvionics","AST SpaceMobile","Embratel Star One","SpaceQuest, Ltd.","Bank Rakyat Indonesia (BRI)","University of Toronto, Institute for Aerospace Studies","BRITE Consortium","UnseenLabs","AstroForge","Broadcasting Satellite System Corp.","Broadcasting Satellite System Corp./Sky Perfect JSAT Corporation","Defence Science and Technology Group/University of New South Wales","China Academy of Space Technology (CAST)","Satellogic S.A.","Bulsatcom","Capital Technology University","Centre National d'Etudes Spatiales (CNES)/NASA","University of Louisiana at Lafayette","Capella Space","Indian Space Research Organization (ISRO)","Korea Aerospace Research Institute (KARI)","Canadian Space Agency","China National Space Administration (CNSA)/National Institute for Space Research (Brazil)","Surrey Satellite Technology Ltd.","Earth-i/Surrey Satellite Technology Ltd.","Canon Electronics","Air Force Research Laboratory","Fleet Space Technologies","Beijing Future Navigation Technology Co. Ltd.","NASA Goddard Space Flight Center","Ministry of Armed Forces","Defense Innovation Unit/Cesium Astro","China National Space Administration (CNSA)/National Centre for Space Studies (CNES)","TELNET Holding","National Aeronautics and Space Administration (NASA) Goddard Space Flight Center","Spacety Aerospace Company","Shanghai Engineering Center for Microsatellites","Spacety Co. Ltd.","Nanjing University","Epic Aerospace","University of Florida","Chinese Academy of Sciences","GeoOptics Inc.","GeoOptics, Inc.","Ciel Satellite Group","University of California-Berkeley/Imperial College-London","Laboratory for Atmospheric and Space Physics, University of Colorado, Boulder","Utah State University","Unknown US agency","National Aeronautics and Space Administration (NASA)/Colorado State University","Department of Defense/Missile Defense Agency","FH Aachen","Armed Forces","Plan-S","US Air Force/ US Navy/NASA","Astro Digital","Taiwan's National Space Organization/National Oceanographic and Atmospheric Admistration (NOAA)","National Space Program Office (NSPO)/University Corporation for Atmospheric Research (UCAR) Boulder, CO","Italian Space Agency/Ministry of Defense","California Polytechnic State University/NASA JPL","University of Colorado","Directorate General of Armaments (DGA)","Argentinian Ministry of Science, Technology and Productive Innovation/Radio Club Bariloche","University of Illinois Urbana-Champaign","Department of Astronautics, University of Tokyo","National Aeronautics and Space Administration (NASA)","Department of Astrophysical and Planetary Science, UC Boulder/National Aeronautics and Space Administration (NASA)","University of Michigan/NASA Earth Science Technology Office","German Orbital Systems","Mexican Space Agency/NanoAvionics","Japan Aerospace Exploration Agency (JAXA)","North Idaho STEM Charter Academy","ADA Space (?)","China Amateur Satellite - CAMSAT","Deimos Imaging/DMC International Imaging (DMCII)","Technical University, Delft","Massachusetts Institute of Technology","Dubai Electricity and Water Authority (DEWA)","Khalifa University","DARPA (Defense Advanced Research Projects Agency)","Sky and Space Global, UK","SpacePharma","IT University of Copenhagen, University of Southern Denmark, Aalborg University and Aarhus University","Philippines’ Department of Science and Technology, University of the Philippines Diliman, and Japan’s Hokkaido University and Tohoku University","Deutsches Zentrum für Luft- und Raumfahrt","Mohammend Bin Rashid Space Centre (MBRSC)","DoD/NOAA","University of Southern California, Space Engineering Research Center/Lockheed Martin","Planet Labs, Inc.","China National Space Administration","Kawasaki Heavy Industries","Singapore Armed Forces","Emirates Institution for Advanced Science & Technology (EIAST)","Academy of Military Science","ESPACE","Global Eagle Entertainment","OHB Italia","Echostar Satellite Services, LLC","HughesNet leased from Echostar Technologies, LLC","Echostar Satellite Services, LLC/Intelsat","Equator Technological University","Airbus","National Authority for Remote Sensing and Space Science (NARSS)","Momentus","Roshydromet - Planeta","University of California","DGA (Arms Procurement Agency)/Centre National d'Etudes Spatiales (CNES)","Clyde Space Ltd./EUTELSAT","Astroscale","Defence Research and Development Organization","EOS Data Analytics","Earth Sciences Enterprise (NASA)","Goddard Space Flight Center/EOS Data and Operations System","National Aeronautics and Space Administration (NASA) - Earth Science Enterprise/Japan Meteorological Agency/Brazilian Space Agency","Defense Ministry","ImageSat International, NV/Ministry of Defense","EUTELSAT S.A./Es'hailSat","Es’hailSat","ESA/European Maritime Safety Agency","European University Network","Ethiopian Space Science and Technology Institute","EUTELSAT Americas","EUTELSAT S.A./Nilesat","exactEarth","Defense Advanced Research Projects Agency (DARPA)","California Polytechnic Institute","Russian Satellite Communications Company","Exseed Space","CNES (Centre national d'études spatiales)","Colombian Air Force","US Air Force Academy","InSpace","University of Texas - Austin","Link Space Aerospace Technology","China Meteorological Administration","National Aeronautics and Space Administration (NASA)/GSFC","University of Stuttgart","US Navy","National Space Organization","Los Alamos National Laboratory","Jihua Laboratory","Copernicus Land and Marine Environment services","AMSAT-UK","PanAmSat (Intelsat S.A.)","PanAmSat (Intelsat S.A.)/Sky Perfect JSAT Corp.","Intelsat S.A.","PanAmSat (Intelsat S.A.)/DirecTV, Inc.","Gama","China National Academy of Sciences (CNSAS)","China’s Ministry of Land and Resources, Ministry of Environmental Protection, and Ministry of Agriculture","State Oceanic Administration (SOA)","China's Ministry of Land and Resources, Ministry of Environmental Protection, and Ministry of Agriculture","Ministry of Natural Resources/Ministry of Housing and Urban-Rural Development/National Bureau of Statistics","People's Liberation Army (C41)","GomSpace ApS","Air Force Research Laboratory/Globalstar","NearSpace Launch/Air Force Research Laboratory","Geespace","Bigelow Aerospace","Korea Meteorological Administration/National Meteorological Satellite Center","DigitalGlobe Corporation","Institute of Space and Astronautical Science (ISAS)/NASA/ESA","Marshall Intec","GHGSat, Inc.","Orbital Sidekick","Globalstar","OHB SE (Orbitale Hochtechnologie Bremen)","PlanetiQ","NOAA (National Oceanographic and Atmospheric Administration)","Turkish Ministry of National Defense","Gonets Satcom","JAXA, Ministry of Environment, National Institute of Environmental Studies","Lunasonde","LuxGovSat","National Aeronautics and Space Administration (NASA)/JAXA","NASA/German Research Centre for Geosciences (GFZ)","Axelspace","Indian Navy","Indian Air Force","Air Force Satellite Control Network","U.S. Army’s Space and Missile Defense Command","Department of Defense/Army Space and Missile Defense Command","Sanya Institute of Remote Sensing","Xiamen University/Aerospace Dongfanghong Satellite Co. Ltd. {CASC)","Department of Defense/Space Test Program","Hunan Hangsheng Satellite Technology Co., Ltd.","US Army Space and Missile Defense Command","HawkEye 360","HEAD Aerospace","Centre National d'Etudes Spatiales (CNES)/Délégation Générale de l'Armement (DGA)","Hellas-Sat Consortium Ltd.","Hellas-Sat Consortium Ltd./INMARSAT","Tokyo Institute of Technology","Hiber Global","Japan Meteorological Agency/Meteorological Satellite Center (MSC)","Institute of Space and Aeronautical Science/NASA","Spacety","Hispasat","National Remote Sensing Center (NRSCC)","China Centre for Resources Satellite Data and Application (CRESDA)","University of Tokyo and NESTRA","PIESAT","China Aerospace Science and Technology Corporation (CASC)","China Aerospace Science and Industry Corporation (CASIC)","Horizons 2 Satellite, LLC (Intelsat, Sky Perfect JSAT Corporation)","Egyptian Space Agency","Kyushu Institute of Technology (KIT)","Harris Corporation","Shanghai Lizheng Satellite Application Technology","Ministry of Ecology and Environment/Ministry of Emergency Management","European Space Agency (ESA)/NASA","Huaian Youth Comprehensive Development Base","National Space Science Center (NSSC)","Avanti Communications, PLC","ICEYE Ltd.","Cabinet Satellite Intelligence Center (CSIC)","TÜBİTAK Space Technologies Research Institute","INMARSAT, Ltd.","INMARSAT, Ltd./European Space Agency (ESA)","Astronautic Technology Sdn. Bhd (ATSB)","University of Colorado’s Laboratory for Atmospheric and Space Physics/Indian Institute of Space Science and Technology","NRS Lab. Atmospheres, Milieux, Observations Spatiales (Verrieres)","European Space Operations Centre (ESOC)/NASA/Russia","Intelsat S.A./Sky Perfect JSAT Corp.","National Aeronautics and Space Administration (NASA)/Multinational","National Aeronautics and Space Administration (NASA)/Goddard Space Flight Center","D-Orbit","Iridium Communications, Inc.","National Center for Atmospheric Research (NCKU)","NASA Small Satellite Technology Program","iSky Technology","NASA/CalPoly","TrustPoint, Inc.","ITU Space Systems Design & Test Laboratory","Radio Amateur Society of Thailand (RAST)","National Aeronautics and Space Administration (NASA)/Centre National d'Etudes Spatiales (CNES)/NOAA/EUMETSAT","Sky Perfect JSAT Corporation","Sky Perfect JSAT Corporation/Kacific","Space OK (Shanghai Ok Space Co Ltd.)","Chang Guang Satellite Technology Co. Ltd.","Beijing ZeroG Space Technology Co., Ltd./Hong Kong Aerospace Tech Group","Shanghai Jiao Tong University/APSCO","Gang Hang Ke","Hong Kong Aerospace Technology Group","Chinese University Corporation for Polar Research","Crown Prince Foundation","China Aerospace Science and Technology Corp. (CASC)","Scientific Production Corporation (joint stock creation of Russian Space Agency)","Roscosmos State Corporation","Kazcosmos","JSC KazSat","Ghalam LLP","National University of Singapore","Kepler Communications","US Army Space and Missile Defense Command/Army Forces Strategic Command","Revolutionary Guard Corps","GUMUSH AeroSpace/University of Turkish Aeronautical Association (UTAA)","Tsinghua University","Tokyo Metropolitan College of Industrial Technology","KLEO Connect","Chosun University","KT Corporation/Korean Agency for Defense Development (ADD)","KT Corporation","National Institute of Technology at Kochi College","Kleos Space","College of Engineering, King Saud University","Kuwait University","Lacuna Space","Lacuna Space/NanoAvionics","Beijing Commsat Technology Development Co. Ltd.","National Aeronautics and Space Administration (NASA)/US Geological Survey","Laos National Authority for Science and Technology","Indonesian National Aeronautics and Space Agency (Lembaga Penerbangan dan Antariksa Nasional - LAPAN)","Aprize Satellite Argentina","US Space Force","Sapienza","Spire Global Inc.","California Polytechnic State University","Harbin Institute/China Amateur Satellite - CAMSAT","General Atomics Electromagnetic Systems","Xinwei Telecom Technology Company","Beijing ZeroG Technology Co. Ltd.","Nanjing and Hong Kong Universities","Changchun Institute of Optics","Russian Federal Space Agency","Federal Security Service (FSB)","SkyFox Labs","Shanghai Academy of Space Technology","University of Vigo/Alén Space","Wuhan University","Lynk Global Inc.","University of Michigan/Montana University","Defence Research and Development Canada (DRDC)/Canadian Space Agency","CTRS Morocco/Institut für Luft-und Raumfahrttechnik (Berlin)","Max Valier school Bolzano, Italy, Oskar von Miller school, Merano, Italy","Cape Peninsula University of Technology (CPUT)","MEASAT Satellite Systems Sdn. Bhd.","Indian Space Research Organization (ISRO)/Centre National d'Etudes Spatiales (CNES)","Open Cosmos","PT Telkomunikasi","National Reconnaissance Office (NRO)/US Air Force","Military Space Forces (VKS)","Analytical Space","Russian Federal Service For Hydrometeorology and Environmental Monitoring (ROSHYDROMET)","EUMETSAT (European Organization for the Exploitation of Meteorological Satellites)","ESA/EUMETSAT (European Organization for the Exploitation of Meterological Satellites)","Space Logistics LLC","Mexico Telecomm","Masdar Institute of Science and Technology","Vietnam National Space Center","MIT/Lincoln Laboratory-University of Massachusetts Amherst","Kingdom of Morocco","Technical University of Munich","Mozhaisky Space Engineering Academy","Mobile Satellite Ventures","DoD/US Navy","ACMEO","Tyvak Nanosatellite Systems, Inc.","Instituto Nacional de Técnia Aeroespacial (INTA)","Brazilian National Institute of Space Research (INPE/MCTI), Federal University of Santa Maria (UFSM)","Shanghai Weixing Keji","Thai Air Force","National Authority for Remote Sensing and Space Sciences","DoD/US Air Force","Center of Excellence for Space Sciences and Technologies (SPACE-SI)","Origin Space","Deimos","Unknown","Würzburg Center for Telematics","Korea Advanced Institute of Science and Technology (KAIST)","Nihon University","NigComSat","National Space Research and Development Agency (NASRDA)","Egyptian Radio and TV Union","Echostar Corporation (entire payload leased from Telesat Canada Ltd.)","Ningxia Jingui Information Technology Co. Ltd.","Noorul Islam University","PT Pasifik Satelit Nntara","National Oceanographic and Atmospheric Administration (NOAA) (part of international program)","Novosibirsk State University","Norwegian Space Center","Norwegian Space Center/Statsat","UK Government/Surrey Satellite Technologies","National Oceanographic and Atmospheric Administration (NOAA)/NASA","F Space Test Office","NSLComm","National Aeronautics and Space Administration (NASA)-Ames Research Center/Stanford University","O3b Networks Ltd.","Michigan Technological University/Air Force Research Laboratory","Swedish National Space Board","U.S. Space Force","OneWeb Satellites","Spanish Space Agency","Italian Defense Ministry","Optus Communications (Parent: Singapore Telecom)","Optus Communications (Parent: Singapore Telecom)/Australian Ministry of Defense","ORBCOMM Inc.","DARPA/Tethers Unlimited","Portland State Aerospace Society","F /ORSO (Operationally Responsive Space Office)","General Atomics - Electromagnetic Systems Group","Mexico Secretariat of National Defense (SEDENA)","Pakistan Space and Upper Atmosphere Research Commission (SUPARCO)/PakSat International","Pakistan Space and Upper Atmosphere Research Commission (SUPARCO)","National Reconnaissance Office","National Aeronautics and Space Administration (NASA)/Cornell University","US Naval Academy","Helios Wire/Echostar Global Australia","Hisdesat","Tiger Innovations","Netherlands Organization for Applied Scientific Research (NTO) consortium","Dauria Aerospace","Peruvian Space Agency","Rocket Labs","Brigham Young University","German Aerospace Center (DLR-IKN)/TESAT Spacecom","University of Chile for Aerospace Investigation)","Ministry of Defense/Centre National d'Etudes Spatiales (CNES) - cooperation with Austria, Belgium, Spain, Sweden","Ministry of Defense//Centre National d/Etudes Spatiales (CNES) - cooperation with Austria, Belgium, Spain, Sweden","Airbus Defense and Space","US Coast Guard","University of Colorado, Boulder","National Technical University","St. Petersburg Polytechnic University","Italian Space Agency","Naval Post-Graduate School","Georgia Institute of Technology","Shanghai Academy of Spaceflight Technology","Astrodynamics and Control Laboratory of Yonsei University","Korean Aerospace Research Institute (KARI)","Von Karman Institute (VKI)","Qiansheng Exploration Technology Co. Ltd.","Shandong Institutes of Industrial Technology","Orbital Space","iQPS","University of Science and Technology","SES S.A. -- total capacity leased to subsidiary of EchoStar Corp.","University of New South Wales/Department of Defence","MDA Corporation","C3S","Vanderbilt University/AMSAT","Robertsville Middle School, Oak Ridge, Tennessee","Korea Advanced Institute of Science and Technology.","Space Technologies Research Institute","Regional African Satellite Communications Organization (RASCOM)","Applied Physics Laboratory/NASA","Reaktor Space Lab","Institute of Space and Astronautical Science (ISAS)/Japan Aerospace Exploration Agency (JAXA)","Skobeltsyn Institute of Nuclear Physics","Indian Space Research Organization (ISRO)/exactEarth","Tohoku University","Tohoku University/Hokkaido University","University of Montpellier","Orbital Solutions Monaco","European Space Agency (ESA) (and 250 international scientific investigators)","National Autonomous University of Mexico","AMSAT/Nepal","National Space Activities Commission (CONAE)","Stanford Student Space Initiative","Department of National Defense","EASF/Bundeswehr","Sateliot IoT","Department of Computer Science and the Faculty of Engineering, Ariel University","Riyadh Space Research Institute","Space Research Institute, King Abdulaziz City for Science and Technology","National Reconnaissance Office (NRO)/US Navy","Strategic Space Command/Space Surveillance Network","Instituto Nacional de Pesquisas Espaciais (INPE)","University of North Carolina - Wilmington","SES S.A./EchoStar Satellite Services, LLC","Telebras/Brazilian Air Force","Teen Satellite Project","NASA Langley Research Center","China Satellite Communication Corp. (China Satcom)","Chinese Academy of Launch Vehicle Technology (CALT)","Shanghai Institute of Satellite Engineering","Chinese Academy of Space Techology (CAST)","National Space Program","Italian Defense Ministry/Telespazio","Italian Defense Ministry/French Defense Ministry","ESA/Royal Meteorological Institute, Belgium","SRI International","Sirius XM Holdings","XM Satellite Radio","China Siwei Surveying and Mapping Technology Co. Ltd.","Sky Mexico","NBN Co (operated by Optus)","DirecTV Latin America/Intelsat","Skykraft","Intelsat/Paradigm Secure Communications (wholly owned by EADS Astrium)","Ministry of Defense/Paradigm Secure Communications (wholly owned by EADS Astrium)","LightSquared","Centre National d'Etudes Spatiales (CNES)/European Space Agency (ESA)","US Southern Command","Seoul National University","National Institute of Information and Communications Technology (JPN)","Astrotech SOHLA","Technical University Dresden","University of Würzburg","National Aeronautics and Space Administration (NASA) Earth Science Office/Laboratory for Atmospheric and Space Physics, Univ. of Colorado","COSMIAC (Configurable Space Microsystems Innovations & Applications Center)","South Asian Association for Regional Cooperation","Swarm Technologies","Hughes Space and Communications Co.","Hisdesat/Ministry of Defense","Air Force Research Laboratory/Swedish Defense Materiel Administration","Omnispace","Endurosat","Astro Space Center of Moscow/Russian Academy of Sciences","Ministry of Defense/General Delegation for Ordnance (DGA)","Spot Image","SRM University","Government of Sudan","Chilean Air Force","Beihang University/APSCO","Asia-Pacific Space Cooperation Organization (APSCO)","Singapore Telecommunications Ltd. (SingTel)/Chunghwa Telecom Co. Ltd.","Sony","Scanway/German Orbital Systems","SatRevolution/Steamjet","Sternula","SatRevolution","Atlas 5","Synspective","Missile Defense Agency (MDA)","University of Chile","Sky Perfect JSAT Corporation/DSN Corp.","Beijing Space View Technology","Goddard Space Flight Center/Penn State University","Ecole Polytechnique Fédérale de Lanne (EPFL)","Naval Research Laboratory","Operational Responsive Space (ORS) Office","Kenya Space Agency","Beijing MinoSpace Technology Co., Ltd.","Minospace","German Aerospace Center (DLR)/Astrium","Alibaba","Orbit Fab","Herzliya Science Center","National Aeronautics and Space Administration (NASA)/SES Americom (SES [Société Européenne des Satellites (SES)])","National Aeronautics and Space Administration (NASA)/Ames Research Center","Teikyo University","AgilSpace","Telesat Canada Ltd. (BCE, Inc.)/APT Satellite Holdings Ltd.","Colorado State University","German Aerospace Center (DLR)/Infoterra","TerraStar Corporation","U.S. Space Force/Other Transaction Authority","Thaicom Public Company Ltd.","National Aeronautics and Space Administration (NASA)/University of California, Berkeley (in partnership with Germany, France, Austria, Canada)","Geo-Informatics and Space Technology Development Agency (GISTDA)","Telenor Satellite Broadcasting","Thuraya Satellite Communications","China Manned Space Engineering Office (CMSEO)","Tianjin University","Chinese Academy of Launch Vehicle Technology (CASIC)","Xiyong Microelectrics Park","Guodian Gaoke","GasTianta and GZH-HNJ BDS AGR Co., Ltd.","Sun Yat-sen University","Insight Position Digital Intelligence Technology Service Co., Ltd.","China Telecom","National University of Defense Technology","China Electronic Technology Group","CASIOM","Spacety Aerospace Company/ThrustMe","Spacety Aerospace Company/Changsha Gaoxinqu Tianyi Research Institute","Chinese Academy of Sciences (CAS)/China Academy of Space Technology","Institute of Software Chinese Academy of Sciences","La Sapienza University of Rome","National Aeronautics and Space Administration (NASA)/Applied Physics Laboratory, Johns Hopkins","Bolivia Aerospace Bureau","Tomorrow.io","University of Malibor/SkyLabs","MyRadar","Tallinn University of Technology","Technical University of Graz","Turkmenistan Ministry of Communications/SSI-Monaco","Turksat","Elbit Systems","UK/DMC International Imaging (DMCII)","UMBRA","Alba Orbital","Wakayama University (UNIFORM consortium)","Polytechnic University of Madrid","University of Versailles Saint-Quentin-en-Yvelines (UVSQ)/National Centre for Scientific Research (CNRS)","NASA/Carnegie Mellon University","National Aeronautics and Space Administration (NASA)/Johns Hopkins University Applied Physics Laboratory","VISIONA Tecnologia Espacial S.A.","Care Weather Technologies","Nanyang Technological University","Centre National d'Etudes Spatiales (CNES)/Israel Space Agency","ViaSat, Inc.","Momentus, Inc.","Vietnamese Posts and Telecommunications Group (VNPT)","C3S LLC","Space Technology Institute-Vietnam Academy of Science and Technology (STI-VAST)","Bolivarian Agency for Space Activities","Shanghai Micro Satellite Engineering Center","CENTI (China-Europe Networks of technology and Innovation)","Military Satellite Communications - US Air Force","WildBlue Communications","La Sapienza University of Rome/Machakos University/University of Nairobi, Kenya","Weathernews, Inc.","Maxar Technologies Inc.","Centre for Research in Satellite Technology (CREST)","MinoSpace Technology","Chengdu Guoxing Aerospace Technology Co. Ltd.","Xingyun Satellite Co.","DFH Satellite Co. Ltd.","European Space Operations Centre (ESOC)","Ministry of Defense/XTAR","DFH Satellite Co. Ltd./AMSAT-China","Chinese Amateur Satellite (CAMSAT)","Loft Orbital/Fugro","Loft Orbital","Gazprom Space Systems","Bauman Moscow State Technical University","GalaxySpace","Galaxy Space","Hubei University of Technology (HUT)","Mitsubishi Heavy Industries","French South African Institute of Technology/Cape Peninsula University of Technology","QOSMOSYS","China Earthquake Administration/Italian Institute for Nuclear Physics","Zhejiang University","Zhuhai Orbita Control Engineering Co. Ltd.","Zhuhai Orbita Aerospace Science and Technology Co."],"operatorCountry":["","USA","United Kingdom","Finland","Denmark","Multinational","Israel","Austria","ESA","Lithuania","Norway","Spain","United Arab Emirates","Kazakhstan","Algeria","Japan","Brazil","Russia","South Korea","Angola","Canada","Argentina","USA/Argentina","China","Belgium","Turkey","Luxembourg","Switzerland","India","France/Italy","Singapore","Azerbaijan","Bangladesh","Czech Republic","Germany","Belarus","Netherlands","Indonesia","France","Australia","Bulgaria","China/Brazil","China/France","Tunisia","Taiwan","Italy","Mexico","Ecuador","Egypt","USA/Canada/Japan","USA/Japan/Brazil","Ethiopia","Colombia","USA/Japan","USA/Germany","France/Italy/Belgium/Spain/Greece","Greece","Greece/United Kingdom","United Kingdom/ESA","Malaysia","USA/India/Singapore/Taiwan","ESA/Russia","Thailand","USA/France","Japan/Singapore","Jordan","Iran","Saudi Arabia","Kuwait","United Kingdom/Netherlands","Laos","Morocco/Germany","South Africa","India/France","Vietnam","Morocco","USA/Canada","Slovenia","Sinapore","Nigeria","Sweden","Pakistan","Peru","New Zealand","Chile","Ukraine","Hungary","India/Canada","Monaco","Nepal","France/Belgium/Sweden","Sudan","Singapore/Taiwan","USA/Poland","Poland/UK","Poland","USA/United Kingdom/Italy","Kenya","Iraq","Bolivia","Estonia","Turkmenistan/Monaco","France/Israel","Venezuela","China/Italy"],"purpose":["","Earth Observation","Technology Development","Communications","Earth Science","Space Science","Space Science/Technology Demonstration","Communications/Technology Development","Communications/Maritime Tracking","Technology Demonstration","Unknown","Navigation/Global Positioning","Earth Observation/Technology Development","Earth Observation/Communications","Earth/Space Observation","Educational","Earth Observation/Earth Science","Platform","Earth Observation/Space Science","Earth Observation/Navigation","Communications/Navigation","Space Observation","Surveillance","Navigation/Regional Positioning","Space Science/Technology Development","Mission Extension Technology","Earth Science/Earth Observation","Earth Observation/Communications/Space Science","Meteorological","Technology Development/Educational","Satellite Positioning"],"detailedPurpose":["","Infrared Imaging","Automatic Identification System (AIS)","Electronic Intelligence","Earth Science","Optical Imaging","Meteorology","Radar Imaging","Amateur Radio","Radar Surveillance","Signals Intelligence","Maritime Surveillance","Radar Imaging (SAR)","Multispectral Imaging","Optical Imaging/Meterology","Optical Imaging/Meteorology","Internet of Things (IoT)/Amateur Radio","Radar Imaging/Earth Science","AI Remote Sensing","Earth Science/Meterology","Early Warning","Hyperspectral Imaging","Optical Stereo Imaging","Subsurface Imaging","Imaging","Maritime Observation","Remote Sensing","Laser Imaging","Thermal Imaging","ADS-B Receiver","Internet of Things (IoT)","Optical Imaging (video)","Video Imaging","Optical Imaging/Automatic Identification System (AIS)","Radio Frequency Monitoring","Meteorology, Automatic Identification System (AIS)","X-ray Astronomy","Technology Development","Synthetic Aperture Radar (SAR)","Optical/Infrared Imaging","Optical/Video Imaging","Radio Spectrum Monitoring","Surveillance","Optical/Hyperspectral Imaging","Situational Awareness","Radar Imaging/Electronic Intelligence","Microwave Radiometer","Meteorology/Earth Science","Data Relay","Optical, Near-Infrared","Synthetic Aperture Imaging","Meteorology/Radar","Navigation","Optical Imaging/Infrared Imaging"],"users":["","Commercial","Civil","Government","Military","Military/Commercial","Government/Military","Military/Government","Government/Civil","Military/Civil","Commercial/Civil","Civil/Commercial","Government/Commercial","Commercial/Government","Government/Commercial/Military","Civil/Government","Civil/Military","Commercial/Military"],"orbitClass":["","LEO","GEO","ELLIPTICAL","MEO"]},"records":[[7530,30,1,3,0,2,1],[19548,141,1,3,0,3,2],[20253,213,1,3,0,4,2],[20580,286,8,5,0,3,1],[20776,525,2,3,0,4,2],[21639,27,1,3,0,12,2],[22049,237,5,5,0,3,3],[22314,575,1,3,0,12,2],[22491,503,16,1,47,3,1],[22787,213,1,3,0,4,2],[22988,9,1,3,0,4,2],[23223,376,1,1,3,4,2],[23467,213,1,3,0,4,2],[23553,390,76,3,0,1,2],[23613,141,1,3,0,3,2],[23628,9,1,3,0,4,2],[23855,376,1,1,3,4,2],[23893,8,1,3,0,4,3],[24674,293,2,3,0,1,2],[24753,162,1,1,19,4,1],[24812,221,1,3,0,1,2],[24876,399,1,11,0,5,4],[24916,221,1,3,0,1,2],[24920,215,1,1,7,3,1],[24936,171,1,3,0,1,2],[25019,9,1,3,0,4,2],[25034,376,1,1,3,4,3],[25071,27,26,3,0,1,2],[25112,432,1,3,0,1,1],[25113,432,1,3,0,1,1],[25114,432,1,3,0,1,1],[25115,432,1,3,0,1,1],[25116,432,1,3,0,1,1],[25117,432,1,3,0,1,1],[25118,432,1,3,0,1,1],[25119,432,1,3,0,1,1],[25153,293,2,3,0,1,2],[25159,432,1,3,0,1,1],[25258,213,1,3,0,4,2],[25336,8,1,1,3,4,2],[25338,414,1,1,19,3,1],[25414,432,1,3,0,1,1],[25415,432,1,3,0,1,1],[25416,432,1,3,0,1,1],[25418,432,1,3,0,1,1],[25419,432,1,3,0,1,1],[25420,432,1,3,0,1,1],[25462,27,26,3,0,1,2],[25475,432,1,3,0,1,1],[25477,432,1,3,0,1,1],[25481,432,1,3,0,1,1],[25504,503,16,1,47,3,1],[25544,300,5,5,0,3,1],[25639,61,2,3,0,4,2],[25652,241,1,3,0,1,1],[25682,346,1,1,4,3,1],[25757,160,34,4,0,3,1],[25867,110,1,5,0,3,3],[25924,5,5,3,0,1,2],[25933,399,1,11,0,5,4],[25967,213,1,3,0,4,2],[25980,432,1,3,0,1,1],[25981,432,1,3,0,1,1],[25982,432,1,3,0,1,1],[25984,432,1,3,0,1,1],[25985,432,1,3,0,1,1],[25989,646,8,5,0,3,3],[25991,162,1,1,19,4,1],[25994,187,49,1,4,3,1],[26038,219,1,3,0,1,2],[26052,9,1,3,0,4,2],[26107,48,1,3,0,1,2],[26356,9,1,1,1,4,2],[26360,399,1,11,0,5,4],[26369,13,5,3,0,1,2],[26388,141,1,3,0,3,2],[26390,518,1,3,0,1,3],[26407,399,1,11,0,5,4],[26410,490,8,5,0,3,3],[26411,490,8,5,0,3,3],[26451,219,1,3,0,1,2],[26463,490,8,5,0,3,3],[26464,490,8,5,0,3,3],[26469,78,16,3,0,1,2],[26473,8,1,1,7,4,1],[26483,518,1,3,0,1,3],[26554,27,36,3,0,1,2],[26575,9,1,3,0,4,2],[26580,27,1,3,0,1,2],[26590,221,1,3,0,1,2],[26605,399,1,11,0,5,4],[26608,219,1,3,0,1,2],[26624,35,20,3,0,1,2],[26626,518,1,3,0,1,3],[26638,27,26,3,0,1,2],[26690,399,1,11,0,5,4],[26694,429,45,3,0,4,2],[26702,425,80,1,4,3,1],[26715,9,1,3,0,4,2],[26719,13,5,3,0,1,2],[26766,219,1,3,0,1,2],[26824,221,1,3,0,1,2],[26853,27,26,3,0,1,2],[26880,9,1,1,1,4,2],[26900,221,1,3,0,1,2],[26958,11,8,9,0,3,1],[26959,70,34,12,5,8,1],[26998,606,1,5,0,8,1],[27004,369,71,2,0,3,1],[27056,61,17,3,0,4,1],[27057,61,17,3,0,4,1],[27168,9,1,3,0,4,2],[27378,173,1,3,0,1,2],[27380,221,1,3,0,1,2],[27389,141,1,3,0,3,2],[27399,312,15,3,0,1,2],[27400,27,26,3,0,1,2],[27414,27,36,3,0,1,2],[27424,189,50,1,4,3,1],[27426,54,1,3,0,1,2],[27434,61,6,1,5,4,1],[27438,221,1,3,0,1,2],[27445,222,1,3,0,1,2],[27460,13,5,3,0,1,2],[27464,61,17,3,0,4,1],[27465,61,17,3,0,4,1],[27509,380,5,1,19,8,2],[27513,221,1,3,0,1,2],[27528,273,11,3,0,14,2],[27540,298,61,5,0,3,3],[27566,141,1,3,0,3,2],[27603,27,36,3,0,1,2],[27606,349,21,3,0,1,1],[27607,500,67,3,8,3,1],[27612,349,21,3,0,1,1],[27640,130,1,1,0,4,1],[27651,535,1,5,0,8,1],[27663,399,1,11,0,5,4],[27691,9,1,3,0,4,2],[27704,399,1,11,0,5,4],[27711,9,1,3,0,4,2],[27715,219,1,3,0,1,2],[27811,266,56,3,0,1,2],[27825,588,12,3,0,1,2],[27831,431,39,3,0,5,2],[27843,97,20,5,0,3,1],[27848,140,15,2,0,2,1],[27854,175,1,3,0,1,2],[27858,97,20,5,0,3,1],[27868,61,17,3,0,4,1],[27869,61,17,3,0,4,1],[27875,9,1,3,0,4,2],[27937,8,1,1,3,4,2],[27939,389,17,2,0,8,1],[27954,220,53,3,0,1,2],[28051,95,28,1,5,3,1],[28054,162,1,1,19,4,1],[28058,117,23,3,0,3,1],[28089,652,17,3,0,1,2],[28117,213,1,3,0,4,2],[28158,9,1,1,1,4,2],[28184,5,5,3,0,1,2],[28187,13,5,3,0,1,2],[28190,399,1,11,0,5,4],[28220,88,23,1,0,3,1],[28252,27,1,3,0,1,2],[28358,221,1,3,0,1,2],[28366,36,22,7,0,1,1],[28369,499,67,2,0,1,1],[28370,499,67,2,0,1,1],[28371,499,67,1,5,3,1],[28372,36,21,7,0,1,1],[28376,188,1,1,4,3,1],[28378,35,20,3,0,1,2],[28384,376,1,3,48,4,3],[28413,88,23,5,0,3,1],[28414,88,23,5,0,3,1],[28419,61,17,3,0,4,1],[28420,61,17,3,0,4,1],[28446,27,1,3,0,1,2],[28470,88,23,1,5,4,1],[28474,399,1,11,0,5,4],[28485,564,96,5,0,8,1],[28492,265,55,1,5,4,1],[28493,394,11,3,0,3,1],[28526,27,36,3,0,1,2],[28537,501,1,1,3,4,1],[28541,501,1,1,3,4,1],[28542,647,11,3,0,7,2],[28626,519,1,3,0,1,2],[28628,293,2,3,0,1,2],[28646,8,1,1,7,4,1],[28649,95,28,1,5,3,1],[28654,414,1,1,6,3,1],[28659,54,1,3,0,1,2],[28702,221,1,3,0,1,2],[28707,202,17,3,0,1,2],[28737,88,23,5,0,3,1],[28786,584,62,3,0,1,2],[28790,219,1,3,0,1,2],[28810,483,15,2,0,3,1],[28868,35,20,3,0,1,2],[28874,399,1,11,0,5,4],[28884,219,1,3,0,1,2],[28885,190,38,3,0,4,2],[28888,8,1,1,5,4,1],[28890,67,23,1,5,1,1],[28899,293,2,3,0,1,2],[28903,54,1,3,0,1,2],[28908,61,17,3,0,4,1],[28912,380,5,1,19,8,2],[28924,13,5,3,0,1,2],[28935,173,1,3,0,1,2],[28945,13,5,3,0,1,2],[28946,540,11,3,0,4,2],[29045,312,15,3,0,1,2],[29047,133,44,1,6,8,1],[29048,133,44,1,6,8,1],[29050,133,44,1,6,8,1],[29051,133,44,1,6,8,1],[29052,133,44,1,6,8,1],[29055,27,26,3,0,1,2],[29079,191,6,1,5,5,1],[29107,125,1,1,7,8,1],[29108,92,38,4,0,3,1],[29155,9,1,1,19,4,2],[29162,197,5,3,0,1,2],[29236,219,1,3,0,1,2],[29249,8,1,1,3,4,3],[29252,234,1,2,0,1,1],[29268,96,18,12,5,12,1],[29270,13,5,3,0,1,2],[29272,312,15,3,0,1,2],[29273,190,38,3,0,4,2],[29349,337,18,3,0,5,2],[29479,271,5,5,0,3,1],[29486,399,1,11,0,5,4],[29494,54,1,3,0,1,2],[29495,430,39,3,0,1,2],[29505,88,23,5,0,3,1],[29506,88,23,5,0,3,1],[29520,519,1,3,0,1,2],[29522,162,1,1,19,4,1],[29526,38,5,3,0,3,2],[29601,399,1,11,0,5,4],[29643,637,1,3,0,1,2],[29644,27,1,3,0,1,2],[29658,128,34,1,7,4,1],[29670,61,17,11,0,5,4],[29671,61,17,11,0,5,4],[29709,348,37,12,5,3,1],[29710,95,28,1,5,3,1],[30580,585,5,5,0,8,3],[30776,206,1,2,0,9,1],[30794,526,2,3,0,4,2],[30797,585,5,5,0,8,3],[30798,585,5,5,0,8,3],[31102,35,20,3,0,1,2],[31118,499,67,1,5,3,1],[31119,499,67,3,0,1,1],[31121,499,67,3,0,1,1],[31124,499,67,3,0,1,1],[31125,499,67,3,0,1,1],[31127,499,67,3,0,1,1],[31304,15,1,1,4,3,1],[31306,27,26,3,0,1,2],[31307,221,1,3,0,1,2],[31571,241,1,3,0,1,1],[31573,241,1,3,0,1,1],[31574,241,1,3,0,1,1],[31576,241,1,3,0,1,1],[31598,134,45,1,7,9,1],[31601,61,6,1,0,4,1],[31698,581,34,1,7,12,1],[31701,501,1,1,3,4,1],[31708,501,1,1,3,4,1],[31789,234,1,2,0,1,1],[31792,61,17,1,3,4,1],[31797,128,34,1,7,4,1],[31800,509,23,3,0,12,2],[31862,54,1,3,0,1,2],[32018,539,1,3,0,1,2],[32019,85,15,3,0,1,2],[32060,640,1,1,5,1,1],[32252,430,39,3,0,1,2],[32253,219,1,3,0,1,2],[32258,636,1,3,0,4,2],[32260,399,1,11,0,5,4],[32263,241,1,3,0,1,1],[32264,241,1,3,0,1,1],[32265,241,1,3,0,1,1],[32275,61,17,11,0,5,4],[32276,61,17,11,0,5,4],[32283,128,34,1,7,4,1],[32293,78,16,3,0,1,2],[32294,526,2,3,0,4,2],[32299,27,80,3,0,1,2],[32376,134,45,1,7,7,1],[32378,376,1,3,48,4,3],[32382,474,20,1,7,1,1],[32384,399,1,11,0,5,4],[32388,280,53,3,0,1,2],[32393,61,17,11,0,5,4],[32395,61,17,11,0,5,4],[32404,588,12,3,0,1,2],[32476,190,6,1,7,4,1],[32478,202,17,3,0,1,2],[32487,587,10,3,0,1,2],[32706,8,1,1,3,4,3],[32711,399,1,11,0,5,4],[32729,54,1,3,0,1,2],[32750,128,34,1,7,4,1],[32763,173,1,3,0,1,2],[32767,630,74,3,0,3,2],[32768,78,16,3,0,1,2],[32779,322,23,3,37,3,2],[32783,95,28,1,5,4,1],[32789,151,36,2,0,2,1],[32790,81,20,2,0,8,1],[32791,406,15,2,0,2,1],[32794,29,6,3,0,5,2],[32951,221,1,3,0,1,2],[32954,61,17,3,0,4,1],[32955,61,17,3,0,4,1],[32956,61,17,3,0,4,1],[33051,509,23,3,0,3,2],[33053,211,1,5,0,3,1],[33055,526,2,3,0,4,2],[33056,614,25,3,0,1,2],[33153,221,1,3,0,1,2],[33154,38,5,3,0,3,2],[33207,173,1,3,0,1,2],[33244,128,34,1,7,4,1],[33274,312,15,3,0,1,2],[33275,27,1,3,0,1,2],[33278,293,2,3,0,1,2],[33320,274,23,1,5,3,1],[33321,274,23,1,5,3,1],[33331,236,1,1,5,12,1],[33373,35,20,3,0,1,2],[33376,221,1,3,0,1,2],[33396,586,62,1,5,3,1],[33401,301,1,5,0,3,3],[33408,88,23,5,0,3,1],[33409,88,23,5,0,3,1],[33412,134,45,1,7,7,1],[33433,88,23,1,0,3,1],[33434,117,23,1,14,3,1],[33436,27,26,3,0,1,2],[33446,65,23,1,5,3,1],[33453,120,20,3,0,1,2],[33459,13,5,3,0,1,2],[33460,13,5,3,0,1,2],[33490,8,1,1,3,4,2],[33492,146,15,1,4,3,1],[33496,532,15,2,0,2,1],[33499,334,15,2,0,2,1],[33591,414,1,1,6,3,1],[33595,202,17,3,0,1,2],[33749,27,36,3,0,1,2],[33750,13,5,3,0,1,2],[33751,545,38,2,1,4,3],[33752,545,38,2,1,4,3],[34111,35,20,3,0,1,2],[34710,13,5,3,0,1,2],[34713,636,1,3,0,4,2],[34810,514,45,3,0,5,2],[34839,65,23,1,5,3,1],[34903,560,1,2,0,4,1],[34941,27,26,3,0,1,2],[35362,372,59,3,0,1,2],[35491,244,1,1,19,3,2],[35493,518,1,3,0,1,2],[35496,582,1,3,0,1,2],[35498,61,17,3,0,4,1],[35500,61,17,3,0,4,1],[35681,150,11,1,5,3,1],[35683,616,2,1,5,3,1],[35684,36,22,8,2,1,1],[35685,394,11,7,0,3,1],[35686,36,22,8,2,1,1],[35696,47,23,3,0,1,2],[35752,399,1,11,0,5,4],[35755,312,15,3,0,1,2],[35756,430,39,3,0,1,2],[35815,440,1,1,3,4,2],[35873,410,20,3,0,1,2],[35932,565,27,2,0,2,1],[35935,309,25,2,0,2,1],[35942,25,11,3,5,1,2],[35943,128,34,3,0,4,2],[35946,640,1,1,5,1,1],[35951,162,1,1,19,4,1],[36032,27,36,3,0,1,2],[36033,587,10,3,0,1,2],[36036,528,8,1,4,3,1],[36037,11,8,9,0,3,1],[36088,88,23,5,0,3,1],[36095,61,17,1,3,4,1],[36097,221,1,3,0,1,2],[36101,13,5,3,0,1,2],[36106,299,1,3,0,1,2],[36108,636,1,3,0,4,2],[36110,65,23,1,5,3,1],[36111,61,17,11,0,5,4],[36112,61,17,11,0,5,4],[36121,65,23,1,5,3,1],[36122,648,23,3,0,2,1],[36124,265,55,1,5,4,1],[36131,54,1,3,0,1,2],[36358,61,17,3,0,4,2],[36395,141,1,5,0,3,2],[36397,221,1,3,0,1,2],[36400,61,17,11,0,5,4],[36401,61,17,11,0,5,4],[36402,61,17,11,0,5,4],[36411,244,1,1,19,3,2],[36413,65,23,1,3,3,1],[36414,65,23,1,3,3,1],[36415,65,23,1,3,3,1],[36499,173,1,3,0,1,2],[36508,11,8,1,7,3,1],[36516,27,26,3,0,1,2],[36581,27,26,3,0,1,2],[36582,128,34,3,0,4,2],[36585,399,1,11,0,5,4],[36592,38,5,3,0,3,2],[36596,88,23,2,0,3,1],[36605,571,34,1,7,3,1],[36608,61,6,1,5,4,1],[36744,96,18,13,15,3,2],[36745,38,5,3,0,3,2],[36792,173,1,3,0,1,2],[36795,95,28,1,5,3,1],[36797,16,10,3,2,3,1],[36798,20,14,1,5,3,1],[36828,65,23,11,0,7,2],[36830,409,48,3,0,3,2],[36831,480,5,3,0,1,2],[36834,65,23,1,7,4,1],[36985,322,23,1,5,3,1],[37139,61,17,11,0,5,4],[37150,509,23,3,0,1,2],[37152,61,17,3,0,4,1],[37154,61,17,3,0,4,1],[37158,146,15,23,0,3,2],[37162,8,1,1,7,4,1],[37165,65,23,1,0,4,1],[37166,661,23,5,0,2,1],[37167,661,23,5,0,2,1],[37168,502,1,21,0,4,1],[37179,88,23,1,0,3,1],[37180,88,23,1,0,3,1],[37185,518,1,3,0,1,2],[37188,241,1,3,0,1,1],[37189,241,1,3,0,1,1],[37190,241,1,3,0,1,1],[37191,241,1,3,0,1,1],[37192,241,1,3,0,1,1],[37193,241,1,3,0,1,1],[37207,85,15,3,0,1,2],[37210,65,23,11,0,7,2],[37212,377,17,3,0,4,3],[37214,210,23,1,6,3,1],[37216,134,45,1,7,7,1],[37218,527,1,3,0,1,2],[37224,422,1,5,0,8,1],[37227,208,1,2,0,9,1],[37232,8,1,1,3,4,2],[37234,229,23,3,0,4,2],[37237,289,2,3,0,1,2],[37238,221,1,3,0,1,2],[37256,65,23,11,0,7,2],[37258,13,5,3,0,1,2],[37264,273,11,3,0,1,2],[37265,338,18,3,0,1,2],[37344,180,17,1,6,3,2],[37348,8,1,1,5,4,1],[37364,8,1,2,0,4,1],[37372,61,17,11,0,5,4],[37377,376,1,3,48,4,2],[37384,65,23,11,0,7,2],[37386,501,1,1,3,4,1],[37387,485,87,1,5,3,1],[37388,95,28,5,0,3,1],[37389,641,30,1,5,3,1],[37391,501,1,1,3,4,1],[37392,221,1,3,0,1,2],[37393,18,12,3,0,5,2],[37398,377,17,3,0,4,3],[37481,9,1,1,1,4,2],[37602,35,20,3,0,1,2],[37605,95,28,20,0,3,2],[37606,552,92,3,0,1,2],[37677,509,23,3,0,3,2],[37730,88,23,2,0,3,1],[37737,322,23,3,37,3,2],[37739,241,1,3,0,1,1],[37740,241,1,3,0,1,1],[37741,241,1,3,0,1,1],[37742,241,1,3,0,1,1],[37743,241,1,3,0,1,1],[37744,241,1,3,0,1,1],[37746,95,28,3,0,3,2],[37748,27,26,3,0,1,2],[37749,326,13,3,0,1,2],[37753,399,1,11,0,5,4],[37755,544,5,5,0,3,3],[37763,65,23,11,0,7,2],[37765,88,23,2,0,3,1],[37775,27,26,3,0,1,2],[37776,86,15,3,0,1,2],[37779,438,81,3,0,12,2],[37781,226,23,1,6,3,1],[37789,408,79,1,5,3,1],[37790,408,79,12,5,3,1],[37791,479,25,1,5,3,1],[37792,36,20,3,2,1,1],[37793,199,20,3,2,1,1],[37804,229,23,3,0,4,2],[37809,27,26,3,0,1,2],[37810,38,5,3,0,3,2],[37813,291,15,1,5,3,1],[37816,198,5,3,0,1,2],[37818,566,1,2,0,4,3],[37826,472,1,3,0,1,2],[37834,221,1,3,0,1,2],[37836,13,5,3,0,1,2],[37838,373,73,1,4,3,1],[37841,547,28,2,0,2,1],[37843,628,1,3,0,1,2],[37846,11,8,11,0,1,4],[37847,11,8,11,0,1,4],[37849,419,1,1,6,3,1],[37855,367,1,2,0,2,1],[37867,61,17,11,0,5,4],[37868,61,17,11,0,5,4],[37869,61,17,11,0,5,4],[37875,65,23,1,0,4,1],[37930,117,23,1,14,3,1],[37931,88,23,1,0,3,1],[37933,47,23,3,0,1,2],[37941,65,23,1,3,4,1],[37948,65,23,11,0,7,2],[37951,360,17,3,0,3,2],[37954,291,15,1,7,3,1],[38007,182,38,1,3,4,1],[38008,182,38,1,3,4,1],[38009,182,38,1,3,4,1],[38010,182,38,1,3,4,1],[38011,549,84,1,5,6,1],[38012,453,29,1,5,3,1],[38014,407,79,3,0,1,2],[38038,275,23,1,5,3,1],[38040,241,1,3,0,1,1],[38041,241,1,3,0,1,1],[38042,241,1,3,0,1,1],[38043,241,1,3,0,1,1],[38044,241,1,3,0,1,1],[38045,241,1,3,0,1,1],[38046,275,23,1,5,3,1],[38049,210,23,1,4,3,2],[38070,636,1,3,0,4,2],[38087,27,26,3,0,1,2],[38091,65,23,11,0,7,2],[38093,391,1,3,0,4,2],[38098,221,1,3,0,1,2],[38107,37,23,3,0,1,2],[38109,8,1,1,7,4,1],[38245,18,12,3,0,5,2],[38248,61,28,1,7,4,1],[38250,65,23,11,0,7,4],[38251,65,23,11,0,7,4],[38254,9,1,3,0,4,2],[38256,322,23,1,5,3,1],[38257,65,23,1,7,4,1],[38331,312,15,3,0,1,2],[38332,630,74,3,0,3,2],[38337,146,53,1,4,3,1],[38338,96,18,1,5,12,1],[38339,146,15,2,0,3,1],[38340,282,15,2,0,2,1],[38342,35,20,3,0,1,2],[38352,229,23,3,0,7,2],[38354,65,23,1,5,4,1],[38356,221,1,3,0,1,2],[38358,141,1,5,0,3,1],[38466,376,1,3,48,4,2],[38528,8,1,1,3,4,2],[38551,173,1,3,0,1,2],[38552,380,5,1,19,8,2],[38652,27,26,3,0,1,2],[38707,323,17,1,5,3,1],[38708,74,35,1,5,3,1],[38710,72,34,2,0,1,1],[38730,322,23,3,0,3,2],[38733,61,17,3,0,4,1],[38740,221,1,3,0,1,2],[38741,289,2,3,0,1,2],[38749,221,1,3,0,1,2],[38752,623,1,1,4,3,3],[38753,623,1,1,4,3,3],[38755,546,90,1,5,1,1],[38758,501,1,1,3,4,1],[38759,262,1,2,0,4,1],[38760,10,1,2,0,3,1],[38764,121,1,5,0,2,1],[38766,262,1,2,0,4,1],[38771,381,5,1,19,8,1],[38773,501,1,1,3,4,1],[38775,65,23,11,0,7,4],[38778,27,26,3,0,1,2],[38779,95,28,3,0,3,2],[38782,633,103,1,5,3,1],[38833,399,1,11,0,5,4],[38857,11,8,11,0,1,4],[38858,11,8,11,0,1,4],[38860,463,23,2,0,3,1],[38861,463,23,2,0,3,1],[38867,221,1,3,0,1,2],[38908,200,1,2,0,4,1],[38953,65,23,11,0,7,2],[38977,360,17,3,0,3,2],[38978,652,17,3,0,1,2],[38991,78,16,3,0,1,2],[38992,13,5,3,0,1,2],[38995,377,17,3,0,4,3],[38998,88,23,2,0,3,1],[38999,645,23,2,0,3,1],[39008,173,1,3,0,1,2],[39011,65,23,1,3,4,1],[39012,65,23,1,3,4,1],[39013,65,23,1,3,4,1],[39017,509,23,3,0,3,2],[39019,454,38,1,5,1,1],[39020,13,5,3,0,1,2],[39022,652,17,3,0,1,2],[39030,245,25,1,5,4,1],[39034,526,2,3,0,4,2],[39035,383,46,3,0,6,2],[39057,61,17,3,0,4,1],[39058,61,17,3,0,4,1],[39059,61,17,3,0,4,1],[39061,291,15,1,7,3,1],[39062,291,15,1,5,3,1],[39068,96,18,2,0,3,1],[39070,301,1,3,0,3,2],[39072,241,1,3,0,1,1],[39073,241,1,3,0,1,1],[39074,241,1,3,0,1,1],[39075,241,1,3,0,1,1],[39076,241,1,3,0,1,1],[39077,241,1,3,0,1,1],[39078,25,11,3,0,1,2],[39079,58,31,3,0,3,2],[39084,346,1,1,4,3,1],[39086,373,73,1,4,3,1],[39088,495,20,21,0,4,1],[39089,97,20,21,0,3,1],[39091,612,7,2,0,2,1],[39120,9,1,1,1,4,2],[39122,197,5,3,0,1,2],[39127,35,20,3,0,1,2],[39150,224,23,1,5,3,1],[39155,61,17,11,0,5,4],[39157,509,23,3,0,1,2],[39159,11,8,1,4,3,1],[39160,632,74,1,5,3,1],[39163,13,5,3,0,1,2],[39166,399,1,11,0,5,4],[39168,636,1,3,0,4,2],[39172,27,26,3,0,1,2],[39177,61,17,1,5,4,1],[39186,360,17,1,5,12,1],[39188,423,2,3,0,1,4],[39189,423,2,3,0,1,4],[39190,423,2,3,0,1,4],[39191,423,2,3,0,1,4],[39197,141,1,5,0,3,1],[39199,95,28,23,0,3,2],[39202,88,23,2,0,3,1],[39206,391,1,3,0,4,2],[39208,88,23,2,0,4,1],[39209,117,23,2,0,3,1],[39210,88,23,2,0,3,1],[39215,294,58,7,0,12,2],[39216,95,28,1,6,3,2],[39222,636,1,3,0,4,2],[39227,96,18,1,7,12,1],[39232,8,1,1,5,4,1],[39233,192,5,3,0,1,2],[39234,253,28,3,0,4,2],[39237,29,6,3,0,5,2],[39239,65,23,1,3,4,1],[39240,65,23,1,3,4,1],[39241,65,23,1,3,4,1],[39249,246,17,3,0,1,1],[39250,246,17,3,0,1,1],[39251,246,17,3,0,1,1],[39253,146,15,5,0,3,3],[39256,9,1,3,0,4,2],[39260,210,23,1,6,3,1],[39265,97,20,4,0,3,1],[39285,27,26,3,0,1,2],[39358,88,23,2,0,3,1],[39360,518,1,3,0,1,2],[39375,61,17,3,0,4,2],[39410,65,23,1,5,4,1],[39416,36,20,3,2,1,1],[39417,658,72,29,0,2,1],[39418,164,1,1,5,1,1],[39419,168,12,1,5,3,1],[39420,428,11,2,0,3,1],[39423,639,15,1,5,1,1],[39425,36,22,8,2,1,1],[39430,230,4,2,0,1,1],[39440,138,21,2,0,2,1],[39444,218,36,3,0,2,1],[39451,11,8,1,4,3,1],[39452,11,8,1,4,3,1],[39453,11,8,1,4,3,1],[39455,88,23,1,0,3,1],[39460,27,26,3,0,1,2],[39462,8,1,1,7,4,1],[39467,23,1,2,0,4,1],[39468,529,1,3,0,4,1],[39472,262,1,2,0,4,1],[39473,567,1,2,0,4,1],[39474,262,1,2,0,4,1],[39476,293,2,3,0,1,2],[39481,607,99,3,0,3,2],[39483,61,17,3,0,4,1],[39484,61,17,3,0,4,1],[39485,61,17,3,0,4,1],[39487,202,17,3,0,1,2],[39498,95,28,3,0,3,2],[39500,584,62,3,0,1,2],[39504,141,1,3,0,3,2],[39508,5,5,3,0,1,2],[39509,56,29,3,0,6,2],[39522,614,25,3,0,1,2],[39533,399,1,11,0,5,4],[39574,250,53,1,4,3,1],[39612,202,17,3,0,1,2],[39613,202,17,3,0,1,2],[39616,25,11,3,0,1,2],[39617,27,26,3,0,1,2],[39624,88,23,2,0,3,1],[39634,380,8,1,4,3,1],[39635,95,28,23,0,3,2],[39650,61,6,1,7,4,1],[39652,376,1,1,3,4,2],[39727,360,17,3,0,3,2],[39728,326,13,3,0,1,2],[39731,325,13,1,5,3,1],[39741,399,1,11,0,5,4],[39751,376,1,3,48,4,2],[39761,61,17,3,0,4,1],[39762,61,17,3,0,4,1],[39763,61,17,3,0,4,1],[39766,146,15,1,7,3,1],[39767,619,15,1,5,2,1],[39768,531,15,2,0,1,1],[39769,487,15,1,5,2,1],[39770,406,15,2,0,2,1],[39773,13,5,3,0,1,2],[40001,61,17,11,0,5,4],[40010,325,13,1,5,3,1],[40011,276,15,2,0,3,1],[40013,150,11,1,5,3,1],[40014,89,21,2,0,1,1],[40015,276,15,2,0,3,1],[40018,36,1,8,2,1,1],[40019,36,22,8,2,1,1],[40020,81,20,5,0,2,1],[40037,447,17,3,2,1,1],[40039,447,17,3,2,1,1],[40042,458,85,2,0,2,1],[40043,605,98,1,4,2,1],[40044,352,1,2,0,1,1],[40045,12,1,2,0,1,1],[40046,12,1,2,0,1,1],[40053,546,90,1,5,1,1],[40055,81,20,2,0,8,1],[40056,81,20,2,0,8,1],[40059,141,1,1,4,3,1],[40061,246,17,3,0,1,1],[40062,246,17,3,0,1,1],[40063,246,17,3,0,1,1],[40069,379,17,1,6,3,1],[40070,484,17,1,4,3,1],[40072,164,1,1,5,1,1],[40075,16,10,3,2,3,1],[40079,423,2,3,0,1,4],[40080,423,2,3,0,1,4],[40081,423,2,3,0,1,4],[40082,423,2,3,0,1,4],[40086,432,1,3,0,1,1],[40087,432,1,3,0,1,1],[40091,432,1,3,0,1,1],[40100,255,1,21,24,4,2],[40105,399,1,11,0,5,4],[40107,47,23,3,0,1,2],[40109,65,23,1,5,4,1],[40110,65,23,1,5,4,1],[40111,65,23,1,5,4,1],[40115,640,1,1,53,1,1],[40118,224,23,1,5,3,1],[40119,82,5,5,0,3,1],[40128,11,8,11,0,1,3],[40129,11,8,11,0,1,3],[40136,356,23,2,0,1,1],[40137,117,23,1,14,3,1],[40141,47,23,3,0,1,2],[40143,65,23,1,7,4,1],[40144,598,23,13,2,3,1],[40146,430,39,3,0,1,2],[40147,372,59,3,0,1,2],[40208,124,1,3,0,4,2],[40258,61,17,3,0,4,2],[40261,88,23,2,0,3,1],[40267,270,15,1,6,3,2],[40269,95,28,23,0,3,2],[40271,221,1,3,0,1,2],[40272,44,21,3,0,1,2],[40275,65,23,1,5,4,1],[40277,202,17,3,0,1,2],[40286,88,23,2,0,3,1],[40294,399,1,11,0,5,4],[40296,377,17,3,0,4,3],[40298,49,15,1,5,3,1],[40301,282,15,1,4,2,1],[40305,65,23,1,7,4,1],[40310,65,23,1,5,4,1],[40315,61,17,11,0,5,4],[40332,95,28,3,0,3,2],[40333,54,1,3,0,1,2],[40336,98,41,1,5,3,1],[40338,65,23,1,3,4,1],[40339,65,23,1,3,4,1],[40340,65,23,1,3,4,1],[40344,8,1,1,3,4,3],[40345,652,17,3,0,1,2],[40348,423,2,3,0,1,4],[40349,423,2,3,0,1,4],[40350,423,2,3,0,1,4],[40351,423,2,3,0,1,4],[40358,61,17,1,3,4,1],[40360,360,17,27,33,12,1],[40362,65,23,1,3,4,1],[40364,27,26,3,0,1,2],[40367,210,23,1,4,3,2],[40374,391,1,3,0,4,2],[40376,141,1,1,4,3,1],[40380,135,1,1,4,8,1],[40381,291,15,1,7,3,1],[40384,293,2,3,0,1,2],[40420,61,17,1,3,4,1],[40424,5,5,3,0,1,2],[40425,13,5,3,0,1,2],[40482,141,1,5,0,3,3],[40483,141,1,5,0,3,3],[40484,141,1,5,0,3,3],[40485,141,1,5,0,3,3],[40505,202,17,3,0,1,2],[40534,399,1,11,0,5,4],[40536,96,18,1,5,12,1],[40538,291,15,1,5,3,1],[40544,11,8,11,0,1,4],[40545,11,8,11,0,1,4],[40547,95,28,23,0,3,2],[40549,65,23,11,0,7,2],[40552,246,17,3,0,1,1],[40553,246,17,3,0,1,1],[40554,246,17,3,0,1,1],[40555,61,17,2,0,4,1],[40613,587,10,3,0,1,2],[40614,515,29,3,0,4,2],[40617,613,101,3,0,12,2],[40657,232,1,2,0,3,1],[40663,54,1,3,0,1,2],[40664,521,46,3,0,1,2],[40697,380,8,1,4,3,1],[40699,61,17,1,5,4,1],[40701,229,23,1,5,4,1],[40715,99,2,1,5,1,1],[40716,99,2,1,5,1,1],[40717,99,2,1,5,1,1],[40718,99,2,2,0,1,1],[40730,399,1,11,0,5,4],[40732,380,5,1,19,8,2],[40733,78,16,3,0,1,2],[40746,636,1,3,0,4,2],[40748,65,23,11,0,7,4],[40749,65,23,11,0,7,4],[40874,221,1,3,0,1,2],[40875,198,5,3,0,1,2],[40878,65,23,1,3,4,1],[40880,95,28,3,0,12,2],[40882,293,2,3,0,1,2],[40887,391,1,3,0,4,2],[40889,11,8,11,0,1,4],[40890,11,8,11,0,1,4],[40892,88,23,2,3,3,2],[40894,224,23,1,5,3,1],[40895,202,17,3,0,1,2],[40899,598,23,2,0,3,1],[40901,661,23,2,0,2,1],[40902,661,23,2,0,2,1],[40903,649,23,3,0,2,1],[40904,322,23,2,0,3,1],[40905,333,23,2,0,2,1],[40906,649,23,3,0,2,1],[40907,649,23,3,0,2,1],[40908,354,23,2,0,2,1],[40910,649,23,3,0,2,1],[40911,649,23,3,0,2,1],[40912,149,23,2,0,2,1],[40914,333,23,2,0,2,1],[40920,61,17,3,0,4,1],[40921,61,17,3,0,4,1],[40922,61,17,3,0,4,1],[40925,463,23,2,0,3,1],[40930,53,28,5,0,3,1],[40931,348,37,1,4,3,1],[40932,352,1,1,35,1,1],[40933,352,1,1,35,1,1],[40934,352,1,1,35,1,1],[40935,352,1,1,35,1,1],[40936,199,20,3,2,1,1],[40938,65,23,11,0,7,2],[40940,522,39,3,0,1,2],[40941,44,21,3,0,1,2],[40946,383,46,3,0,3,2],[40958,359,23,1,37,1,1],[40959,315,23,1,31,1,1],[40960,315,23,1,31,1,1],[40961,315,23,1,5,1,1],[40964,501,1,1,3,4,1],[40965,12,1,2,0,1,1],[40966,12,1,2,0,1,1],[40968,73,1,12,5,2,1],[40970,262,1,2,0,4,1],[40972,262,1,2,0,4,1],[40973,461,1,5,0,4,1],[40974,517,1,9,0,1,1],[40975,262,1,2,0,4,1],[40976,461,1,5,0,4,1],[40977,517,1,9,0,1,1],[40981,501,1,1,3,4,1],[40982,37,23,3,0,1,2],[40984,614,25,3,0,1,2],[40988,322,23,1,5,3,1],[41019,399,1,11,0,5,4],[41021,509,23,3,0,12,2],[41026,65,23,1,3,4,1],[41028,95,28,3,0,3,2],[41029,38,5,3,0,3,2],[41032,61,17,1,20,4,3],[41034,347,70,3,0,3,2],[41036,35,20,3,0,1,2],[41038,65,23,1,3,4,1],[41103,509,23,3,0,1,2],[41105,180,17,1,6,3,2],[41121,61,17,3,0,4,2],[41166,626,30,2,0,2,1],[41167,328,30,1,5,2,1],[41168,57,30,2,0,1,1],[41169,578,30,1,5,1,1],[41171,626,30,2,0,2,1],[41173,117,23,5,0,3,1],[41174,11,8,11,0,1,4],[41175,11,8,11,0,1,4],[41179,432,1,3,0,1,1],[41182,432,1,3,0,1,1],[41183,432,1,3,0,1,1],[41184,432,1,3,0,1,1],[41185,432,1,3,0,1,1],[41186,432,1,3,0,1,1],[41187,432,1,3,0,1,1],[41188,432,1,3,0,1,1],[41189,432,1,3,0,1,1],[41191,202,17,3,4,1,2],[41194,224,23,1,5,3,2],[41238,69,35,3,0,3,2],[41240,311,63,1,4,3,1],[41241,95,28,23,0,3,2],[41310,13,5,3,0,1,2],[41328,399,1,11,0,5,4],[41330,61,17,11,0,5,4],[41334,8,1,1,7,4,1],[41335,380,8,1,4,3,1],[41380,27,26,3,0,1,2],[41382,13,5,3,0,1,2],[41384,95,28,23,0,3,2],[41386,360,17,1,0,12,1],[41394,61,17,1,3,4,1],[41434,65,23,11,0,7,2],[41456,380,8,1,4,3,1],[41460,4,4,1,2,2,1],[41464,28,17,5,0,15,1],[41469,95,28,23,0,3,2],[41471,312,15,3,0,1,2],[41473,65,23,1,3,4,1],[41549,11,8,11,0,1,4],[41550,11,8,11,0,1,4],[41552,584,62,3,0,1,2],[41554,61,17,11,0,5,4],[41556,275,23,1,5,3,1],[41579,61,17,4,0,4,1],[41581,221,1,3,0,1,2],[41584,8,1,1,3,4,2],[41586,65,23,11,0,7,2],[41588,5,5,3,0,1,2],[41589,197,5,3,0,1,2],[41591,80,37,3,0,1,2],[41592,173,1,3,0,1,2],[41599,95,28,1,5,3,1],[41601,164,1,1,5,1,1],[41602,239,20,4,0,1,1],[41603,348,37,1,2,3,1],[41604,72,34,1,5,3,1],[41605,368,20,1,2,3,1],[41622,391,1,3,0,4,2],[41634,88,23,2,0,3,1],[41724,376,1,3,48,4,2],[41725,597,23,3,0,3,2],[41727,226,23,1,7,3,1],[41729,312,15,3,0,1,2],[41731,471,23,5,0,3,1],[41744,255,1,21,24,4,2],[41745,255,1,21,24,4,2],[41747,221,1,3,0,1,2],[41748,221,1,3,0,1,2],[41752,95,28,1,6,3,2],[41759,61,6,1,5,4,1],[41770,448,82,1,5,3,1],[41771,164,1,1,5,1,1],[41772,164,1,1,5,1,1],[41773,164,1,1,5,1,1],[41774,164,1,1,5,1,1],[41784,95,28,2,5,3,1],[41785,20,14,1,5,3,1],[41786,20,14,1,5,3,1],[41787,75,1,1,5,1,1],[41788,81,20,2,0,8,1],[41789,24,14,2,0,3,1],[41790,95,28,1,47,3,1],[41793,95,28,3,0,3,2],[41794,522,39,3,0,1,2],[41836,270,15,1,6,3,2],[41838,509,23,2,0,3,2],[41841,322,23,2,0,3,1],[41849,481,1,2,0,3,1],[41850,102,1,2,0,4,1],[41852,12,1,2,0,1,1],[41853,12,1,2,0,1,1],[41854,215,1,2,0,4,1],[41855,215,1,2,0,4,1],[41857,463,23,1,0,3,1],[41859,11,8,11,0,1,4],[41860,11,8,11,0,1,4],[41861,11,8,11,0,1,4],[41862,11,8,11,0,1,4],[41866,244,1,1,19,3,2],[41869,322,23,3,2,3,2],[41871,352,1,1,35,1,1],[41872,352,1,1,35,1,1],[41873,352,1,1,35,1,1],[41874,352,1,1,35,1,1],[41875,245,25,1,5,4,1],[41877,95,28,1,5,3,1],[41879,636,1,3,0,4,2],[41882,210,23,1,6,3,2],[41884,143,1,1,17,3,1],[41885,143,1,1,17,3,1],[41886,143,1,1,17,3,1],[41887,143,1,1,17,3,1],[41888,143,1,1,17,3,1],[41889,143,1,1,17,3,1],[41890,143,1,1,17,3,1],[41891,143,1,1,17,3,1],[41893,174,1,3,0,1,2],[41896,146,15,5,0,3,3],[41898,210,23,1,4,3,1],[41899,112,23,1,13,3,1],[41900,112,23,1,21,3,1],[41901,112,23,1,21,3,1],[41903,312,15,3,0,1,2],[41904,78,16,3,0,1,2],[41907,563,23,1,5,1,1],[41908,563,23,1,5,1,1],[41911,463,23,2,0,3,2],[41913,322,23,2,0,3,1],[41914,315,23,1,5,1,1],[41917,303,1,3,0,12,1],[41918,303,1,3,0,12,1],[41919,303,1,3,0,12,1],[41920,303,1,3,0,12,1],[41921,303,1,3,0,12,1],[41922,303,1,3,0,12,1],[41923,303,1,3,0,12,1],[41924,303,1,3,0,12,1],[41925,303,1,3,0,12,1],[41926,303,1,3,0,12,1],[41937,9,1,1,1,4,2],[41940,61,15,3,0,4,2],[41942,273,11,3,0,1,2],[41944,375,37,3,0,1,2],[41945,523,16,3,0,1,2],[41948,95,28,1,5,3,1],[41949,95,28,1,5,3,1],[41954,95,28,1,5,3,1],[41965,164,1,1,5,1,1],[41966,164,1,1,5,1,1],[41968,164,1,1,5,1,1],[41972,164,1,1,5,1,1],[41975,164,1,1,5,1,1],[41977,164,1,1,5,1,1],[41978,164,1,1,5,1,1],[41988,164,1,1,5,1,1],[41990,164,1,1,5,1,1],[41991,352,1,1,35,1,1],[41992,352,1,1,35,1,1],[41993,352,1,1,35,1,1],[41994,352,1,1,35,1,1],[41995,352,1,1,35,1,1],[41996,352,1,1,35,1,1],[41997,352,1,1,35,1,1],[41998,352,1,1,35,1,1],[42000,157,27,2,0,1,1],[42001,164,1,1,5,1,1],[42009,164,1,1,5,1,1],[42014,164,1,1,5,1,1],[42015,446,36,2,0,3,1],[42018,164,1,1,5,1,1],[42019,164,1,1,5,1,1],[42023,164,1,1,5,1,1],[42026,164,1,1,5,1,1],[42027,164,1,1,5,1,1],[42028,164,1,1,5,1,1],[42029,164,1,1,5,1,1],[42031,164,1,1,5,1,1],[42034,164,1,1,5,1,1],[42041,164,1,1,5,1,1],[42048,164,1,1,5,1,1],[42058,501,1,1,3,4,1],[42061,591,23,12,0,3,1],[42063,380,8,1,4,3,1],[42065,501,1,1,3,4,1],[42070,173,1,3,0,1,2],[42072,291,15,1,7,3,1],[42075,636,1,3,0,4,2],[42432,27,26,3,0,1,2],[42662,88,23,2,0,3,2],[42689,8,1,2,0,4,1],[42691,338,18,3,0,1,2],[42692,506,16,3,0,17,2],[42695,537,28,3,0,3,2],[42698,293,2,3,0,1,2],[42709,27,26,3,0,1,2],[42719,61,17,1,20,4,3],[42738,146,15,23,0,3,2],[42740,628,1,3,0,1,2],[42741,13,5,3,0,1,2],[42747,95,28,3,0,3,2],[42749,173,1,3,0,1,2],[42752,352,1,1,35,1,1],[42753,352,1,1,35,1,1],[42754,352,1,1,35,1,1],[42755,352,1,1,35,1,1],[42758,288,23,5,0,3,1],[42759,662,23,1,32,1,1],[42760,89,21,1,5,1,1],[42761,662,23,1,32,1,1],[42766,412,28,2,0,2,1],[42767,95,28,1,5,3,1],[42769,101,15,2,5,1,1],[42771,352,1,1,35,1,1],[42772,352,1,1,35,1,1],[42773,352,1,1,35,1,1],[42774,352,1,1,35,1,1],[42775,3,3,2,0,2,1],[42777,127,34,2,0,8,1],[42778,370,45,24,0,2,1],[42779,352,1,1,35,1,1],[42780,352,1,1,35,1,1],[42781,352,1,1,35,1,1],[42782,352,1,1,35,1,1],[42783,156,2,2,0,1,1],[42785,156,2,2,0,1,1],[42786,156,2,2,0,1,1],[42792,488,38,4,0,2,1],[42793,118,1,1,6,1,1],[42795,393,1,9,0,1,1],[42801,90,40,3,0,1,2],[42803,303,1,3,0,12,1],[42804,303,1,3,0,12,1],[42805,303,1,3,0,12,1],[42806,303,1,3,0,12,1],[42807,303,1,3,0,12,1],[42808,303,1,3,0,12,1],[42809,303,1,3,0,12,1],[42810,303,1,3,0,12,1],[42811,303,1,3,0,12,1],[42812,303,1,3,0,12,1],[42814,267,57,3,0,1,2],[42815,95,28,3,0,3,2],[42818,221,1,3,0,1,2],[42825,324,17,1,5,3,1],[42826,416,10,26,2,3,1],[42828,416,10,1,2,3,1],[42829,64,34,9,0,2,1],[42831,212,34,18,2,2,1],[42835,639,15,1,5,1,1],[42837,352,1,1,35,1,1],[42838,352,1,1,35,1,1],[42839,352,1,1,35,1,1],[42840,352,1,1,35,1,1],[42841,352,1,1,35,1,1],[42842,352,1,1,35,1,1],[42844,393,1,2,0,1,1],[42845,352,1,1,35,1,1],[42846,131,1,1,0,1,1],[42847,131,1,1,0,1,1],[42848,118,1,1,6,1,1],[42849,118,1,1,6,1,1],[42900,429,45,1,5,4,1],[42901,627,102,1,5,3,1],[42907,61,17,3,0,5,2],[42915,141,1,3,0,3,2],[42917,146,15,23,0,3,2],[42920,214,44,1,5,3,1],[42921,435,1,9,0,4,1],[42922,155,1,2,0,4,1],[42934,25,11,3,0,1,2],[42939,61,17,11,0,5,4],[42941,8,1,1,3,4,3],[42942,47,23,3,0,1,2],[42945,65,23,1,3,4,1],[42946,65,23,1,3,4,1],[42947,65,23,1,3,4,1],[42949,376,1,3,48,4,2],[42950,221,1,3,0,1,2],[42951,85,15,3,0,1,2],[42954,633,103,1,5,3,1],[42955,303,1,3,0,12,1],[42956,303,1,3,0,12,1],[42957,303,1,3,0,12,1],[42958,303,1,3,0,12,1],[42959,303,1,3,0,12,1],[42960,303,1,3,0,12,1],[42961,303,1,3,0,12,1],[42962,303,1,3,0,12,1],[42963,303,1,3,0,12,1],[42964,303,1,3,0,12,1],[42965,146,15,23,0,3,2],[42967,505,26,3,0,1,2],[42969,380,8,1,4,3,1],[42982,330,1,12,5,4,1],[42984,338,18,3,0,1,2],[42987,164,1,1,5,1,1],[42988,164,1,1,5,1,1],[42989,164,1,1,5,1,1],[42990,164,1,1,5,1,1],[42991,164,1,1,5,1,1],[42992,164,1,1,5,1,1],[42997,164,1,1,5,1,1],[43001,65,23,11,0,7,4],[43002,65,23,11,0,7,4],[43005,387,75,1,5,3,1],[43010,210,23,1,6,3,1],[43011,264,23,1,2,1,1],[43013,414,1,1,6,3,1],[43014,87,39,2,0,9,1],[43017,476,1,2,8,2,1],[43022,315,23,1,5,1,1],[43023,315,23,1,5,1,1],[43024,315,23,1,5,1,1],[43028,65,23,1,3,4,1],[43029,65,23,1,3,4,1],[43030,65,23,1,3,4,1],[43032,61,17,1,3,4,1],[43034,229,23,1,5,4,1],[43039,20,14,3,0,3,2],[43041,352,1,1,35,1,1],[43045,352,1,1,35,1,1],[43047,352,1,1,35,1,1],[43048,352,1,1,35,1,1],[43050,305,1,2,0,3,1],[43051,352,1,1,35,1,1],[43053,352,1,1,35,1,1],[43054,352,1,1,35,1,1],[43055,11,8,11,0,1,4],[43056,11,8,11,0,1,4],[43057,11,8,11,0,1,4],[43058,11,8,11,0,1,4],[43065,146,15,1,0,3,1],[43070,303,1,3,0,12,1],[43071,303,1,3,0,12,1],[43072,303,1,3,0,12,1],[43073,303,1,3,0,12,1],[43074,303,1,3,0,12,1],[43075,303,1,3,0,12,1],[43076,303,1,3,0,12,1],[43077,303,1,3,0,12,1],[43078,303,1,3,0,12,1],[43079,303,1,3,0,12,1],[43080,229,23,1,5,4,1],[43081,65,23,1,3,4,1],[43082,65,23,1,3,4,1],[43083,65,23,1,3,4,1],[43099,563,23,1,5,1,1],[43100,563,23,1,5,1,1],[43107,65,23,11,0,7,4],[43108,65,23,11,0,7,4],[43111,95,28,1,5,3,1],[43113,35,20,3,35,1,1],[43114,290,3,1,7,1,1],[43115,100,2,2,0,1,1],[43116,95,28,2,0,3,1],[43118,131,1,1,0,1,1],[43123,352,1,1,35,1,1],[43124,352,1,1,35,1,1],[43125,352,1,1,35,1,1],[43126,352,1,1,35,1,1],[43127,51,1,2,0,1,1],[43130,43,1,2,0,1,1],[43131,386,1,1,4,15,1],[43143,118,1,1,6,1,1],[43144,393,1,9,0,1,1],[43145,8,1,1,7,4,1],[43146,229,23,1,5,4,1],[43152,49,15,1,7,3,1],[43155,602,23,2,0,1,1],[43156,287,23,2,0,2,1],[43157,329,2,3,30,1,1],[43158,602,23,2,0,1,1],[43159,315,23,1,5,1,1],[43160,315,23,1,5,1,1],[43162,9,1,1,1,4,2],[43165,352,1,1,35,1,1],[43167,352,1,1,35,1,1],[43169,634,23,2,0,3,1],[43170,65,23,1,3,4,1],[43171,65,23,1,3,4,1],[43172,65,23,1,3,4,1],[43174,18,12,3,0,1,2],[43175,27,26,3,0,1,2],[43178,249,26,3,0,6,2],[43180,324,17,1,5,3,1],[43181,324,17,1,5,3,1],[43182,352,1,1,35,1,1],[43183,352,1,1,35,1,1],[43184,352,1,1,35,1,1],[43185,352,1,1,35,1,1],[43186,64,34,2,0,2,1],[43187,64,34,2,0,2,1],[43188,64,34,2,0,2,1],[43189,64,34,2,0,2,1],[43192,209,23,2,0,1,1],[43194,660,104,4,0,3,1],[43195,89,21,1,21,1,1],[43196,230,4,2,0,3,1],[43197,230,4,1,0,4,1],[43199,507,23,2,0,2,1],[43204,89,21,1,21,1,1],[43207,65,23,11,0,7,4],[43208,65,23,11,0,7,4],[43215,444,11,1,7,5,1],[43223,291,15,1,5,3,1],[43226,244,1,1,19,3,2],[43228,273,11,3,0,1,2],[43231,423,2,3,0,1,4],[43232,423,2,3,0,1,4],[43233,423,2,3,0,1,4],[43234,423,2,3,0,1,4],[43236,229,23,1,5,4,1],[43245,65,23,11,0,7,4],[43246,65,23,11,0,7,4],[43249,303,1,3,0,12,1],[43250,303,1,3,0,12,1],[43251,303,1,3,0,12,1],[43252,303,1,3,0,12,1],[43253,303,1,3,0,12,1],[43254,303,1,3,0,12,1],[43255,303,1,3,0,12,1],[43256,303,1,3,0,12,1],[43257,303,1,3,0,12,1],[43258,303,1,3,0,12,1],[43259,225,23,1,5,3,1],[43260,225,23,1,5,3,1],[43262,225,23,1,5,3,1],[43271,562,15,3,0,17,2],[43272,289,2,3,0,1,2],[43275,65,23,1,3,4,1],[43276,65,23,1,3,4,1],[43277,65,23,1,3,4,1],[43279,634,23,2,0,3,1],[43286,95,28,23,0,3,2],[43339,9,1,3,0,4,2],[43432,61,17,3,0,5,2],[43435,141,1,5,0,3,3],[43437,380,8,1,4,3,1],[43439,663,23,1,21,1,1],[43440,662,23,1,32,1,1],[43441,663,23,1,21,1,1],[43442,663,23,1,21,1,1],[43443,663,23,1,21,1,1],[43446,102,1,2,0,4,2],[43450,37,23,3,0,1,2],[43461,225,23,1,21,3,1],[43463,59,32,3,0,3,2],[43476,251,54,1,4,3,1],[43477,251,54,1,4,3,1],[43478,303,1,3,0,12,1],[43479,303,1,3,0,12,1],[43480,303,1,3,0,12,1],[43481,303,1,3,0,12,1],[43482,303,1,3,0,12,1],[43484,225,23,1,5,3,1],[43485,365,23,1,5,2,1],[43488,27,26,3,0,1,2],[43491,210,23,1,6,3,2],[43495,291,15,1,7,3,1],[43508,61,17,11,0,5,4],[43518,403,23,2,0,3,1],[43519,403,23,2,0,3,1],[43529,439,81,1,5,3,1],[43530,439,81,1,5,3,1],[43539,65,23,11,0,7,2],[43547,580,1,5,0,2,1],[43556,12,1,2,0,1,1],[43557,12,1,2,0,1,1],[43558,352,1,1,35,1,1],[43559,352,1,1,35,1,1],[43560,352,1,1,35,1,1],[43561,352,1,1,35,1,1],[43562,35,20,3,0,1,2],[43564,11,8,11,0,1,4],[43565,11,8,11,0,1,4],[43566,11,8,11,0,1,4],[43567,11,8,11,0,1,4],[43569,303,1,3,0,12,1],[43570,303,1,3,0,12,1],[43571,303,1,3,0,12,1],[43572,303,1,3,0,12,1],[43573,303,1,3,0,12,1],[43574,303,1,3,0,12,1],[43575,303,1,3,0,12,1],[43576,303,1,3,0,12,1],[43577,303,1,3,0,12,1],[43578,303,1,3,0,12,1],[43581,65,23,11,0,7,4],[43582,65,23,11,0,7,4],[43585,224,23,1,5,3,3],[43587,375,37,3,0,1,2],[43600,11,8,1,4,3,1],[43602,65,23,11,0,7,4],[43603,65,23,11,0,7,4],[43609,226,23,1,6,3,1],[43611,579,20,3,0,1,2],[43613,141,1,4,27,3,1],[43616,181,1,5,0,10,1],[43618,99,2,1,5,1,1],[43619,418,2,1,7,12,1],[43622,65,23,11,0,7,4],[43623,65,23,11,0,7,4],[43632,58,31,3,0,3,2],[43633,280,53,3,0,1,2],[43636,104,23,2,0,1,1],[43641,493,21,1,7,3,1],[43642,65,23,1,3,4,1],[43647,65,23,11,0,7,4],[43648,65,23,11,0,7,4],[43651,9,1,3,0,4,2],[43655,226,23,1,4,3,1],[43656,572,23,3,0,1,1],[43657,61,17,1,3,4,1],[43662,108,42,1,6,3,1],[43668,593,23,3,0,1,1],[43669,111,23,2,0,1,1],[43672,247,15,1,4,3,1],[43676,168,12,1,5,3,1],[43677,282,15,5,0,2,1],[43678,159,15,1,5,2,1],[43683,65,23,11,0,7,2],[43687,61,17,11,0,5,4],[43689,381,5,1,19,8,1],[43690,118,1,1,6,1,1],[43694,103,39,2,0,1,1],[43695,352,1,1,35,1,1],[43696,103,39,2,0,1,1],[43697,352,1,1,35,1,1],[43698,95,28,3,0,3,2],[43700,193,38,3,0,5,2],[43706,65,23,11,0,7,4],[43707,65,23,11,0,7,4],[43710,88,23,5,0,3,1],[43712,603,23,2,0,3,1],[43713,314,23,3,30,1,1],[43717,387,75,1,5,3,1],[43719,95,28,1,21,3,1],[43720,283,1,3,0,1,1],[43721,205,52,1,5,4,1],[43722,103,39,2,0,1,1],[43723,164,1,1,5,1,1],[43724,164,1,1,5,1,1],[43725,164,1,1,5,1,1],[43729,329,20,3,0,1,1],[43730,75,1,1,5,1,1],[43731,352,1,1,35,1,1],[43732,352,1,1,35,1,1],[43733,164,1,1,5,1,1],[43737,119,1,1,6,1,1],[43738,295,59,2,0,3,1],[43741,164,1,1,5,1,1],[43742,164,1,1,5,1,1],[43743,482,3,1,21,1,1],[43744,269,36,2,0,1,1],[43745,352,1,1,35,1,1],[43746,352,1,1,35,1,1],[43747,164,1,1,5,1,1],[43751,61,17,3,0,4,1],[43752,61,17,3,0,4,1],[43753,61,17,3,0,4,1],[43759,443,1,3,30,1,1],[43764,456,1,3,0,4,1],[43765,263,1,22,3,1,1],[43767,131,1,1,0,1,1],[43768,17,11,1,2,1,1],[43769,164,1,1,5,1,1],[43770,30,1,3,0,2,1],[43772,462,1,2,0,2,1],[43773,462,1,2,0,2,1],[43774,269,36,2,0,1,1],[43775,203,28,3,8,1,1],[43780,388,34,2,0,8,1],[43783,327,13,1,5,1,1],[43785,433,1,2,0,4,1],[43790,172,45,1,2,1,1],[43792,195,8,16,0,2,1],[43793,136,1,5,0,2,1],[43794,263,1,22,3,1,1],[43795,433,1,2,0,4,1],[43796,79,1,2,0,1,1],[43797,164,1,1,5,1,1],[43799,263,1,22,3,1,1],[43800,290,3,1,12,1,1],[43802,164,1,1,5,1,1],[43803,321,65,3,8,2,1],[43804,3,3,2,0,2,1],[43805,19,13,2,0,2,1],[43807,72,34,2,0,3,1],[43808,456,1,3,0,4,1],[43809,103,39,3,0,1,1],[43811,405,18,5,0,3,1],[43812,75,1,1,5,1,1],[43813,79,1,2,0,1,1],[43815,206,1,2,0,9,1],[43816,538,1,3,0,1,1],[43817,538,1,3,0,1,1],[43818,538,1,3,0,1,1],[43819,200,1,2,0,4,1],[43820,504,1,1,13,2,1],[43822,200,1,1,5,4,1],[43823,235,18,1,6,3,2],[43824,95,28,3,0,3,2],[43831,500,67,1,5,3,1],[43833,500,67,1,5,3,1],[43836,345,23,2,30,1,1],[43837,345,23,2,30,1,1],[43838,345,23,2,30,1,1],[43839,345,23,2,30,1,1],[43840,345,23,2,30,1,1],[43841,345,23,2,30,1,1],[43842,345,23,2,30,1,1],[43849,12,1,2,0,1,1],[43850,508,1,2,0,3,1],[43853,105,1,5,0,3,1],[43855,116,1,2,0,8,1],[43856,307,1,5,0,8,1],[43857,147,1,15,0,2,1],[43858,139,1,2,0,2,1],[43860,200,1,5,0,4,1],[43861,12,1,2,0,1,1],[43864,254,28,3,0,4,2],[43866,137,38,1,13,4,1],[43867,61,17,3,0,5,2],[43871,279,23,2,0,1,1],[43873,399,1,11,0,5,4],[43874,88,23,2,0,3,2],[43876,324,17,1,5,3,1],[43877,324,17,1,5,3,1],[43879,306,33,3,29,1,1],[43880,534,34,29,0,2,1],[43881,144,34,2,0,1,1],[43882,352,1,1,35,1,1],[43883,352,1,1,35,1,1],[43884,352,1,1,35,1,1],[43885,352,1,1,35,1,1],[43886,352,1,1,35,1,1],[43887,352,1,1,35,1,1],[43888,352,1,1,35,1,1],[43889,352,1,1,35,1,1],[43890,252,15,1,13,1,1],[43893,164,1,1,5,1,1],[43899,164,1,1,5,1,1],[43902,164,1,1,5,1,1],[43905,164,1,1,5,1,1],[43906,164,1,1,5,1,1],[43907,658,72,1,33,2,1],[43908,364,11,3,0,10,1],[43909,463,23,1,4,3,1],[43910,463,23,1,4,3,1],[43911,463,23,1,4,3,1],[43912,463,23,1,4,3,1],[43913,463,23,1,4,3,1],[43914,278,23,3,0,3,1],[43915,463,23,1,4,3,1],[43917,88,23,2,0,3,2],[43920,509,23,3,0,12,2],[43922,303,1,3,0,12,1],[43923,303,1,3,0,12,1],[43924,303,1,3,0,12,1],[43925,303,1,3,0,12,1],[43926,303,1,3,0,12,1],[43927,303,1,3,0,12,1],[43928,303,1,3,0,12,1],[43929,303,1,3,0,12,1],[43930,303,1,3,0,12,1],[43931,303,1,3,0,12,1],[43932,146,15,2,0,3,1],[43934,486,15,1,5,2,1],[43935,385,74,1,0,3,1],[43937,406,15,3,8,2,1],[43941,8,1,1,5,4,1],[43942,357,23,1,0,1,1],[43943,315,23,1,13,1,1],[43944,111,23,2,0,1,1],[43946,315,23,1,13,1,1],[44034,266,56,3,0,13,2],[44035,95,28,3,0,3,2],[44047,178,48,1,13,3,1],[44048,413,37,3,0,1,2],[44057,427,2,3,0,1,1],[44058,427,2,3,0,1,1],[44059,427,2,3,0,1,1],[44060,427,2,3,0,1,1],[44061,427,2,3,0,1,1],[44062,427,2,3,0,1,1],[44067,509,23,3,0,12,2],[44071,636,1,3,0,4,2],[44072,460,45,1,21,3,1],[44076,322,23,3,0,3,2],[44078,185,28,1,3,4,1],[44080,164,1,1,5,1,1],[44084,352,1,1,35,1,1],[44085,352,1,1,35,1,1],[44086,352,1,1,35,1,1],[44087,352,1,1,35,1,1],[44088,164,1,1,5,1,1],[44090,164,1,1,5,1,1],[44095,164,1,1,5,1,1],[44098,164,1,1,5,1,1],[44103,17,11,1,2,1,1],[44105,76,9,2,0,1,1],[44109,76,9,2,0,1,1],[44112,423,2,3,0,1,4],[44113,423,2,3,0,1,4],[44114,423,2,3,0,1,4],[44115,423,2,3,0,1,4],[44186,38,5,3,0,1,2],[44204,65,23,11,0,7,2],[44207,322,23,1,5,3,1],[44209,322,23,1,5,3,1],[44226,541,80,2,0,4,1],[44229,262,1,2,7,4,1],[44231,65,23,11,0,7,2],[44233,61,28,1,7,4,1],[44299,61,17,11,0,5,4],[44307,652,17,3,0,1,2],[44310,315,23,1,5,1,1],[44311,593,23,3,0,1,1],[44312,88,23,1,6,3,1],[44313,111,23,2,0,1,1],[44314,88,23,1,6,3,1],[44315,599,23,2,0,1,1],[44316,599,23,2,0,1,1],[44322,97,20,1,7,3,1],[44323,97,20,1,7,3,1],[44324,97,20,1,7,3,1],[44333,54,1,3,0,1,2],[44334,13,5,3,0,1,2],[44337,65,23,11,0,7,2],[44339,462,1,2,0,2,1],[44340,420,1,2,0,16,1],[44341,436,1,2,0,1,1],[44343,132,44,1,6,3,1],[44344,102,1,2,0,4,4],[44347,206,1,2,0,9,3],[44349,132,44,1,6,3,1],[44350,132,44,1,6,3,1],[44351,132,44,1,6,3,1],[44353,132,44,1,6,3,1],[44354,442,1,2,0,4,3],[44356,424,1,2,0,4,3],[44358,132,44,1,6,3,1],[44360,353,1,2,35,2,3],[44365,437,46,1,5,4,1],[44367,75,1,1,5,1,1],[44387,379,17,1,6,3,1],[44388,176,47,2,0,2,1],[44389,290,3,1,7,1,1],[44390,290,3,1,7,1,1],[44391,421,6,2,0,1,1],[44392,28,17,5,0,2,1],[44394,28,17,5,0,2,1],[44396,352,1,1,35,1,1],[44399,99,2,2,0,1,1],[44400,534,34,2,0,2,1],[44402,352,1,1,35,1,1],[44403,352,1,1,35,1,1],[44404,28,17,5,0,2,1],[44405,352,1,1,35,1,1],[44406,362,33,2,0,1,1],[44407,352,1,1,35,1,1],[44408,179,1,2,0,1,1],[44409,352,1,1,35,1,1],[44411,352,1,1,35,1,1],[44412,64,34,2,0,2,1],[44414,352,1,1,35,1,1],[44415,398,48,2,0,3,1],[44419,310,62,3,0,2,1],[44421,61,17,2,0,4,1],[44422,61,17,2,0,4,1],[44423,61,17,2,0,4,1],[44424,61,17,2,0,4,1],[44449,65,23,1,3,4,1],[44450,65,23,1,3,4,1],[44451,65,23,1,3,4,1],[44453,377,17,3,0,4,3],[44457,61,17,3,0,5,2],[44475,177,8,3,0,1,2],[44476,221,1,3,0,1,2],[44479,29,6,3,0,5,2],[44481,9,1,3,0,4,2],[44482,9,1,2,0,4,3],[44486,467,23,1,5,1,1],[44487,593,23,3,0,1,1],[44488,643,23,1,5,1,1],[44495,83,38,1,11,1,1],[44497,445,1,2,0,1,1],[44498,445,1,2,0,1,1],[44499,75,1,1,5,1,1],[44506,399,1,11,0,5,4],[44517,61,17,4,0,4,1],[44519,111,23,2,5,1,1],[44520,117,23,5,0,3,1],[44528,275,23,1,21,3,1],[44529,320,23,1,33,2,1],[44534,662,23,1,32,1,1],[44536,662,23,1,21,1,1],[44537,662,23,1,21,1,1],[44538,662,23,1,21,1,1],[44539,662,23,1,21,1,1],[44542,65,23,11,0,7,4],[44543,65,23,11,0,7,4],[44552,61,17,1,20,4,3],[44622,224,23,1,5,3,1],[44624,13,5,3,0,1,2],[44625,382,1,25,0,1,2],[44628,141,1,5,7,3,1],[44634,131,1,9,0,1,1],[44637,88,23,2,0,3,2],[44703,228,23,1,5,3,1],[44704,548,91,1,5,3,1],[44705,284,23,3,0,1,1],[44706,601,42,2,0,1,1],[44709,65,23,11,0,7,2],[44777,315,23,1,13,1,1],[44779,411,23,1,0,1,1],[44780,411,23,1,0,1,1],[44781,411,23,1,0,1,1],[44782,411,23,1,0,1,1],[44783,411,23,1,0,1,1],[44785,335,34,2,0,1,1],[44786,335,34,2,0,1,1],[44793,65,23,11,0,7,4],[44794,65,23,11,0,7,4],[44797,61,17,14,0,4,1],[44800,61,48,3,0,5,2],[44801,293,2,3,0,1,2],[44804,95,28,1,5,3,1],[44806,378,1,2,0,3,1],[44808,164,1,1,13,1,1],[44809,164,1,1,13,1,1],[44811,164,1,1,13,1,1],[44812,164,1,1,13,1,1],[44814,164,1,1,13,1,1],[44816,164,1,1,13,1,1],[44818,164,1,1,13,1,1],[44819,224,23,1,7,3,1],[44824,21,15,4,0,1,1],[44835,61,17,14,0,4,1],[44836,315,23,1,5,1,1],[44838,264,23,1,2,1,1],[44839,264,23,1,2,1,1],[44840,593,23,3,0,1,1],[44841,593,23,3,0,1,1],[44842,111,23,2,0,1,1],[44843,111,23,2,0,1,1],[44850,61,17,11,0,5,4],[44852,615,6,2,0,1,1],[44853,615,6,2,0,1,1],[44855,352,1,1,35,1,1],[44856,470,15,1,7,1,1],[44857,61,28,1,7,4,1],[44859,1,1,1,1,1,1],[44860,352,1,1,35,1,1],[44861,352,1,1,35,1,1],[44863,352,1,1,35,1,1],[44864,65,23,11,0,7,4],[44865,65,23,11,0,7,4],[44868,313,64,3,0,1,2],[44873,134,45,1,7,7,1],[44874,11,8,5,0,3,1],[44876,33,8,3,0,3,1],[44877,204,8,5,0,3,1],[44879,594,23,1,0,1,1],[44880,196,51,1,0,3,1],[44881,595,23,2,0,2,1],[44883,98,41,1,5,3,1],[44903,180,17,1,6,3,2],[44905,246,17,3,0,1,1],[44906,246,17,3,0,1,1],[44907,246,17,3,0,1,1],[44910,278,23,2,0,3,2],[44978,463,23,3,0,3,2],[45016,315,23,1,5,1,1],[45017,89,21,1,0,1,1],[45018,89,21,1,0,1,1],[45019,593,23,3,0,1,1],[45024,654,23,3,0,1,1],[45026,95,28,3,0,3,2],[45027,13,5,3,0,1,2],[45110,8,1,2,0,4,1],[45114,12,1,2,0,4,1],[45116,12,1,2,0,4,1],[45117,12,1,2,0,4,1],[45121,123,1,2,0,10,1],[45125,200,1,2,0,4,1],[45131,427,2,3,0,1,1],[45132,427,2,3,0,1,1],[45133,427,2,3,0,1,1],[45134,427,2,3,0,1,1],[45135,427,2,3,0,1,1],[45136,427,2,3,0,1,1],[45137,427,2,3,0,1,1],[45138,427,2,3,0,1,1],[45139,427,2,3,0,1,1],[45140,427,2,3,0,1,1],[45141,427,2,3,0,1,1],[45142,427,2,3,0,1,1],[45143,427,2,3,0,1,1],[45144,427,2,3,0,1,1],[45145,427,2,3,0,1,1],[45146,427,2,3,0,1,1],[45147,427,2,3,0,1,1],[45148,427,2,3,0,1,1],[45149,427,2,3,0,1,1],[45150,427,2,3,0,1,1],[45151,427,2,3,0,1,1],[45152,427,2,3,0,1,1],[45153,427,2,3,0,1,1],[45154,427,2,3,0,1,1],[45155,427,2,3,0,1,1],[45156,427,2,3,0,1,1],[45157,427,2,3,0,1,1],[45158,427,2,3,0,1,1],[45159,427,2,3,0,1,1],[45160,427,2,3,0,1,1],[45161,427,2,3,0,1,1],[45162,427,2,3,0,1,1],[45163,427,2,3,0,1,1],[45164,427,2,3,0,1,1],[45165,291,15,1,5,3,1],[45245,312,15,3,0,1,2],[45246,235,18,1,6,3,2],[45249,403,23,2,0,3,1],[45250,403,23,2,0,3,1],[45251,403,23,2,0,3,1],[45253,403,23,2,0,3,1],[45254,377,17,3,0,4,3],[45263,466,24,5,0,2,1],[45264,536,1,5,0,3,1],[45344,65,23,11,0,7,2],[45358,61,17,11,0,5,4],[45424,427,2,3,0,1,1],[45425,427,2,3,0,1,1],[45426,427,2,3,0,1,1],[45427,427,2,3,0,1,1],[45428,427,2,3,0,1,1],[45429,427,2,3,0,1,1],[45430,427,2,3,0,1,1],[45431,427,2,3,0,1,1],[45432,427,2,3,0,1,1],[45433,427,2,3,0,1,1],[45434,427,2,3,0,1,1],[45435,427,2,3,0,1,1],[45436,427,2,3,0,1,1],[45437,427,2,3,0,1,1],[45438,427,2,3,0,1,1],[45439,427,2,3,0,1,1],[45440,427,2,3,0,1,1],[45441,427,2,3,0,1,1],[45442,427,2,3,0,1,1],[45443,427,2,3,0,1,1],[45444,427,2,3,0,1,1],[45445,427,2,3,0,1,1],[45446,427,2,3,0,1,1],[45447,427,2,3,0,1,1],[45448,427,2,3,0,1,1],[45449,427,2,3,0,1,1],[45450,427,2,3,0,1,1],[45451,427,2,3,0,1,1],[45452,427,2,3,0,1,1],[45453,427,2,3,0,1,1],[45454,427,2,3,0,1,1],[45455,427,2,3,0,1,1],[45456,427,2,3,0,1,1],[45457,427,2,3,0,1,1],[45460,65,23,1,3,4,1],[45461,65,23,1,3,4,1],[45462,65,23,1,3,4,1],[45465,9,1,3,0,4,2],[45602,644,23,3,0,3,1],[45603,644,23,3,0,3,1],[45605,366,1,3,0,1,1],[45606,350,1,2,0,4,1],[45608,61,17,1,20,4,3],[45610,206,1,2,0,9,1],[45611,403,23,2,0,3,1],[45612,403,23,2,0,3,1],[45624,264,23,1,2,1,1],[45625,224,23,1,5,3,1],[45721,226,23,1,6,3,1],[45723,8,1,10,0,4,1],[45724,8,1,10,0,4,1],[45725,8,1,10,0,4,1],[45726,32,1,6,0,2,1],[45727,473,39,2,0,16,1],[45788,164,1,1,5,1,1],[45789,164,1,1,5,1,1],[45790,164,1,1,5,1,1],[45794,224,23,1,5,3,1],[45795,661,23,2,0,2,1],[45796,264,23,1,2,1,1],[45807,65,23,11,0,7,2],[45854,399,1,11,0,5,4],[45856,227,23,1,13,3,1],[45859,88,23,5,0,3,1],[45860,61,6,1,5,4,1],[45863,37,23,3,0,1,2],[45873,8,1,1,5,4,1],[45874,8,1,1,5,4,1],[45875,8,1,1,5,4,1],[45876,8,1,1,5,4,1],[45916,152,1,2,0,2,1],[45920,31,18,3,0,4,2],[45939,275,23,1,5,3,1],[45941,593,23,2,0,1,1],[45985,202,17,3,0,1,2],[45986,202,17,3,0,1,2],[46025,224,23,1,5,3,1],[46026,333,23,4,0,2,1],[46088,75,1,1,5,1,1],[46089,75,1,1,5,1,1],[46112,85,15,3,0,1,2],[46113,382,1,25,0,1,2],[46114,221,1,3,0,1,2],[46179,164,1,1,5,1,1],[46180,164,1,1,5,1,1],[46200,263,1,22,3,1,1],[46232,224,23,1,5,3,1],[46233,598,23,2,0,4,1],[46234,169,23,2,0,4,1],[46235,164,1,1,5,1,1],[46265,493,21,1,7,3,1],[46266,243,1,4,0,1,1],[46267,393,1,9,0,1,1],[46272,89,21,1,5,1,1],[46273,194,8,1,2,3,1],[46274,302,45,9,0,1,1],[46275,55,1,3,0,1,1],[46276,620,11,2,0,2,1],[46277,400,77,1,40,2,1],[46278,239,20,4,0,1,1],[46279,516,8,4,0,3,1],[46280,609,77,2,0,2,1],[46281,11,8,2,0,3,1],[46284,157,27,5,0,1,1],[46285,164,1,1,5,1,1],[46286,164,1,1,5,1,1],[46288,164,1,1,5,1,1],[46289,164,1,1,5,1,1],[46290,164,1,1,5,1,1],[46291,164,1,1,5,1,1],[46292,217,8,1,0,3,1],[46293,217,8,1,0,3,1],[46294,393,1,2,0,1,1],[46295,393,1,2,0,1,1],[46296,164,1,1,5,1,1],[46297,164,1,1,5,1,1],[46298,352,1,1,35,1,1],[46299,352,1,1,35,1,1],[46312,611,100,1,1,2,1],[46313,164,1,1,5,1,1],[46314,164,1,1,5,1,1],[46315,352,1,1,35,1,1],[46316,352,1,1,35,1,1],[46317,352,1,1,35,1,1],[46318,352,1,1,35,1,1],[46319,329,20,3,0,1,1],[46320,397,62,1,5,4,1],[46396,224,23,1,5,3,3],[46454,315,23,1,5,1,1],[46455,315,23,1,5,1,1],[46456,315,23,1,5,1,1],[46457,315,23,1,5,1,1],[46458,315,23,1,5,1,1],[46459,315,23,1,5,1,1],[46460,315,23,1,32,1,1],[46461,315,23,1,32,1,1],[46462,315,23,1,32,1,1],[46469,226,23,1,4,3,1],[46478,275,23,1,0,3,1],[46479,275,23,1,0,3,1],[46486,246,17,3,0,1,1],[46487,246,17,3,0,1,1],[46488,246,17,3,0,1,1],[46489,384,12,1,4,2,1],[46490,653,17,5,0,2,1],[46491,653,17,5,0,2,1],[46492,343,2,3,30,1,1],[46493,28,17,5,0,2,1],[46494,415,17,5,0,2,1],[46495,64,34,5,0,2,1],[46496,290,3,1,7,1,1],[46497,290,3,1,7,1,1],[46498,329,20,3,0,1,1],[46499,329,20,3,0,1,1],[46500,352,1,1,35,1,1],[46501,352,1,1,35,1,1],[46502,352,1,1,35,1,1],[46503,352,1,1,35,1,1],[46504,404,34,9,0,1,1],[46505,404,34,9,0,1,1],[46506,404,34,9,0,1,1],[46507,404,34,9,0,1,1],[46527,164,1,1,5,1,1],[46528,164,1,1,5,1,1],[46529,164,1,1,5,1,1],[46597,164,1,1,5,1,1],[46609,164,1,1,5,1,1],[46610,224,23,1,5,3,2],[46621,164,1,1,5,1,1],[46735,164,1,1,5,1,1],[46737,164,1,1,5,1,1],[46738,164,1,1,5,1,1],[46805,61,17,11,0,5,4],[46807,65,23,1,3,4,1],[46808,65,23,1,3,4,1],[46809,65,23,1,3,4,1],[46810,593,23,2,0,1,1],[46812,164,1,1,5,1,1],[46813,164,1,1,5,1,1],[46814,164,1,1,5,1,1],[46815,164,1,1,5,1,1],[46816,164,1,1,5,1,1],[46817,164,1,1,5,1,1],[46818,101,15,9,5,1,1],[46819,164,1,1,5,1,1],[46820,164,1,1,5,1,1],[46821,164,1,1,5,1,1],[46822,164,1,1,5,1,1],[46825,164,1,1,5,1,1],[46826,399,1,11,0,5,4],[46827,89,21,1,0,1,1],[46828,89,21,1,0,1,1],[46829,89,21,1,0,1,1],[46830,89,21,1,0,1,1],[46831,89,21,1,0,1,1],[46832,89,21,1,0,1,1],[46833,89,21,1,0,1,1],[46835,89,21,1,0,1,1],[46836,89,21,1,0,1,1],[46840,89,21,1,0,1,1],[46904,593,23,2,0,1,1],[46905,61,28,1,7,4,1],[46906,340,26,1,34,1,1],[46907,340,26,1,34,1,1],[46908,352,1,1,35,1,1],[46909,352,1,1,35,1,1],[46910,352,1,1,35,1,1],[46911,352,1,1,35,1,1],[46912,340,26,1,34,1,1],[46914,340,26,1,34,1,1],[46916,597,23,3,0,3,2],[46918,376,1,1,0,4,4],[46926,352,1,1,35,1,1],[46931,131,1,1,0,1,1],[46941,83,38,1,11,1,1],[46943,83,38,1,11,1,1],[46984,380,8,1,4,3,1],[47202,146,15,3,0,3,2],[47226,190,12,1,5,4,1],[47227,246,17,3,0,1,1],[47228,246,17,3,0,1,1],[47229,246,17,3,0,1,1],[47230,190,17,2,0,4,1],[47231,224,23,1,22,3,1],[47234,117,23,5,0,3,1],[47235,117,23,5,0,3,1],[47237,8,1,1,3,4,2],[47253,559,15,1,7,1,1],[47256,95,28,3,0,3,2],[47258,427,2,3,0,1,1],[47259,427,2,3,0,1,1],[47260,427,2,3,0,1,1],[47261,427,2,3,0,1,1],[47262,427,2,3,0,1,1],[47263,427,2,3,0,1,1],[47264,427,2,3,0,1,1],[47265,427,2,3,0,1,1],[47266,427,2,3,0,1,1],[47267,427,2,3,0,1,1],[47268,427,2,3,0,1,1],[47269,427,2,3,0,1,1],[47270,427,2,3,0,1,1],[47271,427,2,3,0,1,1],[47272,427,2,3,0,1,1],[47273,427,2,3,0,1,1],[47274,427,2,3,0,1,1],[47275,427,2,3,0,1,1],[47276,427,2,3,0,1,1],[47277,427,2,3,0,1,1],[47278,427,2,3,0,1,1],[47279,427,2,3,0,1,1],[47280,427,2,3,0,1,1],[47281,427,2,3,0,1,1],[47282,427,2,3,0,1,1],[47283,427,2,3,0,1,1],[47284,427,2,3,0,1,1],[47285,427,2,3,0,1,1],[47286,427,2,3,0,1,1],[47287,427,2,3,0,1,1],[47288,427,2,3,0,1,1],[47289,427,2,3,0,1,1],[47290,427,2,3,0,1,1],[47291,427,2,3,0,1,1],[47292,427,2,3,0,1,1],[47293,427,2,3,0,1,1],[47294,376,1,10,0,4,1],[47295,376,1,10,0,4,1],[47296,593,23,2,0,1,1],[47297,272,23,1,7,1,1],[47298,403,23,9,0,3,1],[47299,656,23,2,0,2,1],[47300,196,51,1,5,3,1],[47302,65,23,1,7,4,1],[47305,137,38,1,13,4,1],[47306,614,25,3,0,1,2],[47309,93,1,2,0,2,1],[47310,457,1,1,46,8,1],[47317,450,1,2,0,8,1],[47318,450,1,2,0,8,1],[47319,201,1,5,0,8,1],[47320,91,1,2,0,8,1],[47321,597,23,3,0,3,2],[47346,242,34,3,0,1,1],[47429,538,1,3,0,1,1],[47430,52,27,3,0,1,1],[47438,621,38,9,0,2,1],[47440,14,9,3,0,1,1],[47441,46,25,1,5,2,1],[47445,533,34,5,0,2,1],[47446,329,20,3,0,1,1],[47448,451,34,2,0,3,1],[47450,352,1,1,35,1,1],[47452,164,1,1,5,1,1],[47453,352,1,1,35,1,1],[47454,329,20,3,0,1,1],[47456,164,1,1,5,1,1],[47457,352,1,1,35,1,1],[47459,538,1,3,0,1,1],[47461,329,20,3,0,1,1],[47462,164,1,1,5,1,1],[47463,622,1,9,0,8,1],[47465,538,1,3,0,1,1],[47467,215,1,2,0,4,1],[47469,164,1,1,5,1,1],[47471,164,1,1,5,1,1],[47472,164,1,1,5,1,1],[47473,164,1,1,5,1,1],[47474,164,1,1,5,1,1],[47475,164,1,1,5,1,1],[47476,329,20,3,0,1,1],[47477,164,1,1,5,1,1],[47478,164,1,1,5,1,1],[47483,622,1,9,0,8,1],[47484,39,1,2,0,2,1],[47485,470,15,1,7,1,1],[47486,329,20,3,0,1,1],[47487,52,27,3,0,1,1],[47488,52,27,3,0,1,1],[47490,164,1,1,5,1,1],[47491,164,1,1,5,1,1],[47492,164,1,1,5,1,1],[47493,352,1,1,35,1,1],[47494,164,1,1,5,1,1],[47495,164,1,1,5,1,1],[47496,164,1,1,5,1,1],[47498,164,1,1,5,1,1],[47500,164,1,1,5,1,1],[47501,329,20,3,0,1,1],[47502,263,1,22,3,1,1],[47503,329,20,3,0,1,1],[47505,263,1,22,3,1,1],[47506,290,3,1,7,1,1],[47507,290,3,1,7,1,1],[47508,263,1,22,3,1,1],[47509,239,20,4,0,1,1],[47510,290,3,1,7,1,1],[47511,352,1,1,35,1,1],[47514,164,1,1,5,1,1],[47515,164,1,1,5,1,1],[47516,164,1,1,5,1,1],[47517,52,27,3,0,1,1],[47518,164,1,1,5,1,1],[47519,52,27,3,0,1,1],[47521,164,1,1,5,1,1],[47522,164,1,1,5,1,1],[47523,164,1,1,5,1,1],[47524,622,1,9,0,8,1],[47525,352,1,1,35,1,1],[47526,141,1,2,0,3,1],[47527,164,1,1,5,1,1],[47528,164,1,1,5,1,1],[47529,352,1,1,35,1,1],[47530,164,1,1,5,1,1],[47531,329,20,3,0,1,1],[47532,65,23,1,3,4,1],[47533,65,23,1,3,4,1],[47536,65,23,1,3,4,1],[47538,352,1,1,35,1,1],[47539,164,1,1,5,1,1],[47540,164,1,1,5,1,1],[47541,269,36,2,0,1,1],[47542,164,1,1,5,1,1],[47543,164,1,1,5,1,1],[47544,164,1,1,5,1,1],[47545,164,1,1,5,1,1],[47546,61,17,1,3,4,1],[47612,164,1,1,5,1,1],[47613,463,23,3,0,3,2],[47615,39,1,2,0,2,1],[47616,39,1,2,0,2,1],[47617,164,1,1,5,1,1],[47684,164,1,1,5,1,1],[47685,164,1,1,5,1,1],[47686,164,1,1,5,1,1],[47687,164,1,1,5,1,1],[47688,164,1,1,5,1,1],[47691,65,23,1,3,4,1],[47693,65,23,1,3,4,1],[47695,65,23,1,3,4,1],[47698,164,1,1,5,1,1],[47699,26,16,1,5,3,1],[47701,491,46,2,0,2,1],[47719,42,17,1,6,3,3],[47851,88,23,2,0,3,2],[47854,65,23,1,3,4,1],[47856,65,23,1,3,4,1],[47857,65,23,1,3,4,1],[47932,96,18,1,13,3,1],[47933,252,15,1,5,1,1],[47934,252,15,1,5,1,1],[47935,252,15,1,5,1,1],[47936,252,15,1,5,1,1],[47937,6,6,2,0,3,1],[47938,464,18,5,0,2,1],[47939,6,6,2,0,3,1],[47940,161,12,1,0,3,1],[47941,638,45,3,0,2,1],[47942,269,36,2,0,1,1],[47943,6,6,2,0,3,1],[47944,184,30,2,0,1,1],[47948,343,69,3,30,1,1],[47949,329,20,3,0,1,1],[47950,336,18,5,0,2,1],[47953,395,16,1,4,8,1],[47954,341,67,2,0,2,1],[47955,329,20,3,0,1,1],[47956,109,43,2,0,1,1],[47957,64,34,9,0,2,1],[47961,497,11,3,30,1,1],[47965,625,1,1,6,2,1],[47966,393,1,9,0,1,1],[47967,473,39,2,0,16,1],[47968,393,1,9,0,1,1],[47969,256,1,1,0,4,1],[47971,75,1,1,5,1,1],[47972,449,83,2,0,1,1],[48042,427,2,3,0,1,1],[48043,427,2,3,0,1,1],[48044,427,2,3,0,1,1],[48045,427,2,3,0,1,1],[48046,427,2,3,0,1,1],[48047,427,2,3,0,1,1],[48048,427,2,3,0,1,1],[48049,427,2,3,0,1,1],[48050,427,2,3,0,1,1],[48051,427,2,3,0,1,1],[48052,427,2,3,0,1,1],[48053,427,2,3,0,1,1],[48054,427,2,3,0,1,1],[48055,427,2,3,0,1,1],[48056,427,2,3,0,1,1],[48057,427,2,3,0,1,1],[48058,427,2,3,0,1,1],[48059,427,2,3,0,1,1],[48060,427,2,3,0,1,1],[48061,427,2,3,0,1,1],[48062,427,2,3,0,1,1],[48063,427,2,3,0,1,1],[48064,427,2,3,0,1,1],[48065,427,2,3,0,1,1],[48066,427,2,3,0,1,1],[48067,427,2,3,0,1,1],[48068,427,2,3,0,1,1],[48069,427,2,3,0,1,1],[48070,427,2,3,0,1,1],[48071,427,2,3,0,1,1],[48072,427,2,3,0,1,1],[48073,427,2,3,0,1,1],[48074,427,2,3,0,1,1],[48075,427,2,3,0,1,1],[48076,427,2,3,0,1,1],[48077,427,2,3,0,1,1],[48079,224,23,1,5,3,1],[48083,64,34,9,0,2,1],[48084,64,34,9,0,2,1],[48085,64,34,9,0,2,1],[48157,88,23,2,0,3,1],[48210,427,2,3,0,1,1],[48211,427,2,3,0,1,1],[48212,427,2,3,0,1,1],[48213,427,2,3,0,1,1],[48214,427,2,3,0,1,1],[48215,427,2,3,0,1,1],[48216,427,2,3,0,1,1],[48217,427,2,3,0,1,1],[48218,427,2,3,0,1,1],[48219,427,2,3,0,1,1],[48220,427,2,3,0,1,1],[48221,427,2,3,0,1,1],[48222,427,2,3,0,1,1],[48223,427,2,3,0,1,1],[48224,427,2,3,0,1,1],[48225,427,2,3,0,1,1],[48226,427,2,3,0,1,1],[48227,427,2,3,0,1,1],[48228,427,2,3,0,1,1],[48229,427,2,3,0,1,1],[48230,427,2,3,0,1,1],[48231,427,2,3,0,1,1],[48232,427,2,3,0,1,1],[48233,427,2,3,0,1,1],[48234,427,2,3,0,1,1],[48235,427,2,3,0,1,1],[48236,427,2,3,0,1,1],[48237,427,2,3,0,1,1],[48238,427,2,3,0,1,1],[48239,427,2,3,0,1,1],[48240,427,2,3,0,1,1],[48241,427,2,3,0,1,1],[48242,427,2,3,0,1,1],[48243,427,2,3,0,1,1],[48244,427,2,3,0,1,1],[48245,427,2,3,0,1,1],[48247,8,1,1,5,4,1],[48248,468,23,1,7,3,1],[48249,468,23,1,5,3,1],[48250,216,23,2,0,3,1],[48251,261,23,2,0,1,1],[48252,593,23,2,0,1,1],[48253,401,23,2,0,1,1],[48254,316,23,1,0,1,1],[48255,316,23,1,0,1,1],[48256,569,23,2,0,1,1],[48261,226,23,1,4,3,1],[48268,455,38,1,5,1,1],[48269,352,1,1,35,1,1],[48270,14,9,3,0,1,1],[48271,393,1,9,0,1,1],[48272,416,10,1,2,3,1],[48273,352,1,1,35,1,1],[48275,589,23,5,0,3,1],[48340,65,23,1,5,4,1],[48423,65,23,1,3,4,1],[48424,65,23,1,3,4,1],[48425,65,23,1,3,4,1],[48426,593,23,2,0,1,1],[48605,94,1,1,12,1,1],[48606,393,1,2,0,1,1],[48618,9,1,1,1,4,2],[48767,427,2,3,0,1,1],[48768,427,2,3,0,1,1],[48769,427,2,3,0,1,1],[48770,427,2,3,0,1,1],[48771,427,2,3,0,1,1],[48772,427,2,3,0,1,1],[48773,427,2,3,0,1,1],[48774,427,2,3,0,1,1],[48775,427,2,3,0,1,1],[48776,427,2,3,0,1,1],[48777,427,2,3,0,1,1],[48778,427,2,3,0,1,1],[48779,427,2,3,0,1,1],[48780,427,2,3,0,1,1],[48781,427,2,3,0,1,1],[48782,427,2,3,0,1,1],[48783,427,2,3,0,1,1],[48784,427,2,3,0,1,1],[48785,427,2,3,0,1,1],[48786,427,2,3,0,1,1],[48787,427,2,3,0,1,1],[48788,427,2,3,0,1,1],[48789,427,2,3,0,1,1],[48790,427,2,3,0,1,1],[48791,427,2,3,0,1,1],[48792,427,2,3,0,1,1],[48793,427,2,3,0,1,1],[48794,427,2,3,0,1,1],[48795,427,2,3,0,1,1],[48796,427,2,3,0,1,1],[48797,427,2,3,0,1,1],[48798,427,2,3,0,1,1],[48799,427,2,3,0,1,1],[48800,427,2,3,0,1,1],[48801,427,2,3,0,1,1],[48802,427,2,3,0,1,1],[48808,210,23,1,6,3,2],[48838,518,1,3,0,1,2],[48840,66,23,1,5,1,1],[48841,401,23,5,0,1,1],[48842,259,23,1,4,8,1],[48844,426,1,21,44,4,1],[48846,8,1,2,0,4,1],[48847,8,1,2,0,4,1],[48848,8,1,2,0,4,1],[48850,477,1,1,13,2,1],[48859,399,1,11,0,5,4],[48860,65,23,1,3,4,1],[48861,65,23,1,3,4,1],[48863,65,23,1,3,4,1],[48864,593,23,2,0,1,1],[48865,61,17,1,45,4,1],[48872,557,95,1,0,1,1],[48873,557,95,1,0,1,1],[48874,126,1,3,0,4,1],[48875,126,1,3,0,4,1],[48876,61,36,1,10,3,1],[48877,260,1,3,5,4,1],[48878,257,1,1,0,4,1],[48882,538,1,3,0,1,1],[48883,538,1,3,0,1,1],[48884,538,1,3,0,1,1],[48885,352,1,1,35,1,1],[48886,538,1,3,0,1,1],[48887,538,1,3,0,1,1],[48888,538,1,3,0,1,1],[48889,538,1,3,0,1,1],[48890,538,1,3,0,1,1],[48891,538,1,3,0,1,1],[48892,393,1,9,0,1,1],[48893,538,1,3,0,1,1],[48894,538,1,3,0,1,1],[48895,538,1,3,0,1,1],[48896,538,1,3,0,1,1],[48897,538,1,3,0,1,1],[48898,393,1,9,0,1,1],[48899,538,1,3,0,1,1],[48900,64,34,9,0,2,1],[48901,141,1,1,6,3,1],[48902,355,1,3,5,1,1],[48903,355,1,3,5,1,1],[48904,538,1,3,0,1,1],[48905,89,21,1,43,1,1],[48906,617,1,1,50,1,1],[48907,200,1,2,0,4,1],[48909,141,1,9,0,3,1],[48910,243,1,4,0,1,1],[48911,650,1,30,0,1,1],[48914,290,3,1,12,1,1],[48915,651,1,3,0,1,1],[48916,290,3,1,12,1,1],[48917,290,3,1,12,1,1],[48918,290,3,1,12,1,1],[48919,89,21,1,0,1,1],[48920,89,21,1,0,1,1],[48921,89,21,1,0,1,1],[48922,145,46,1,5,3,1],[48923,352,1,1,35,1,1],[48924,207,2,17,0,1,1],[48925,352,1,1,35,1,1],[48926,340,26,1,3,1,1],[48927,352,1,1,35,1,1],[48928,437,46,1,5,4,1],[48929,352,1,1,35,1,1],[48930,340,26,1,3,1,1],[48931,263,1,22,3,1,1],[48938,366,1,3,0,1,1],[48942,340,26,1,3,1,1],[48943,469,68,3,0,2,1],[48948,263,1,22,3,1,1],[48950,340,26,1,3,1,1],[48951,573,1,2,0,1,1],[48952,52,27,3,0,1,1],[48953,45,24,1,5,1,1],[48954,52,27,3,0,1,1],[48955,52,27,3,0,1,1],[48957,263,1,22,3,1,1],[48959,352,1,1,35,1,1],[48960,52,27,3,0,1,1],[48961,52,27,3,0,1,1],[48962,238,12,1,0,3,1],[48963,397,62,1,5,4,1],[48964,543,40,2,0,1,1],[48965,11,8,2,0,3,1],[48966,402,11,1,0,3,1],[48967,427,2,3,0,1,1],[48968,427,2,3,0,1,1],[48970,427,2,3,0,1,1],[48971,427,2,3,0,1,1],[48972,427,2,3,0,1,1],[48973,427,2,3,0,1,1],[48974,427,2,3,0,1,1],[48975,427,2,3,0,1,1],[48976,427,2,3,0,1,1],[48977,427,2,3,0,1,1],[48978,427,2,3,0,1,1],[48979,427,2,3,0,1,1],[48980,427,2,3,0,1,1],[48981,427,2,3,0,1,1],[48982,427,2,3,0,1,1],[48984,427,2,3,0,1,1],[48985,427,2,3,0,1,1],[48986,427,2,3,0,1,1],[48987,427,2,3,0,1,1],[48988,427,2,3,0,1,1],[48989,427,2,3,0,1,1],[48990,427,2,3,0,1,1],[48991,427,2,3,0,1,1],[48992,427,2,3,0,1,1],[48993,427,2,3,0,1,1],[48994,427,2,3,0,1,1],[48995,427,2,3,0,1,1],[48996,427,2,3,0,1,1],[48997,427,2,3,0,1,1],[48998,427,2,3,0,1,1],[48999,427,2,3,0,1,1],[49000,427,2,3,0,1,1],[49001,427,2,3,0,1,1],[49002,427,2,3,0,1,1],[49003,315,23,1,5,1,1],[49004,315,23,1,5,1,1],[49005,315,23,1,5,1,1],[49006,315,23,1,5,1,1],[49007,643,23,1,5,1,1],[49008,210,23,1,6,3,1],[49011,322,23,3,0,3,2],[49013,200,1,2,0,4,1],[49014,256,1,1,0,4,1],[49015,200,1,2,0,4,1],[49016,154,12,2,0,2,1],[49018,411,23,1,41,1,1],[49019,411,23,1,41,1,1],[49020,411,23,1,41,1,1],[49021,411,23,1,41,1,1],[49022,411,23,1,41,1,1],[49026,65,23,1,3,4,1],[49027,593,23,2,0,1,1],[49028,65,23,1,3,4,1],[49029,65,23,1,3,4,1],[49049,322,23,1,5,3,1],[49052,102,1,2,0,4,1],[49055,78,16,3,0,1,2],[49056,13,5,3,0,1,2],[49059,335,34,2,0,1,1],[49060,335,34,2,0,1,1],[49062,509,23,3,0,12,2],[49066,83,38,1,11,1,1],[49067,475,86,9,0,1,1],[49068,11,8,5,0,3,1],[49069,351,45,2,0,2,1],[49070,455,38,1,5,1,1],[49071,322,23,1,5,3,1],[49072,322,23,1,5,3,1],[49075,427,2,3,0,1,1],[49076,427,2,3,0,1,1],[49077,427,2,3,0,1,1],[49078,427,2,3,0,1,1],[49079,427,2,3,0,1,1],[49080,427,2,3,0,1,1],[49081,427,2,3,0,1,1],[49082,427,2,3,0,1,1],[49083,427,2,3,0,1,1],[49084,427,2,3,0,1,1],[49085,427,2,3,0,1,1],[49086,427,2,3,0,1,1],[49087,427,2,3,0,1,1],[49088,427,2,3,0,1,1],[49089,427,2,3,0,1,1],[49090,427,2,3,0,1,1],[49091,427,2,3,0,1,1],[49092,427,2,3,0,1,1],[49093,427,2,3,0,1,1],[49094,427,2,3,0,1,1],[49095,427,2,3,0,1,1],[49096,427,2,3,0,1,1],[49097,427,2,3,0,1,1],[49098,427,2,3,0,1,1],[49099,427,2,3,0,1,1],[49100,427,2,3,0,1,1],[49101,427,2,3,0,1,1],[49102,427,2,3,0,1,1],[49103,427,2,3,0,1,1],[49104,427,2,3,0,1,1],[49105,427,2,3,0,1,1],[49106,427,2,3,0,1,1],[49107,427,2,3,0,1,1],[49108,427,2,3,0,1,1],[49112,403,23,3,0,1,1],[49114,403,23,3,0,1,1],[49115,463,23,3,0,3,2],[49122,224,23,1,21,3,1],[49125,509,23,3,0,3,2],[49186,427,2,3,0,1,1],[49187,427,2,3,0,1,1],[49188,427,2,3,0,1,1],[49189,427,2,3,0,1,1],[49190,427,2,3,0,1,1],[49191,427,2,3,0,1,1],[49192,427,2,3,0,1,1],[49193,427,2,3,0,1,1],[49194,427,2,3,0,1,1],[49195,427,2,3,0,1,1],[49196,427,2,3,0,1,1],[49197,427,2,3,0,1,1],[49198,427,2,3,0,1,1],[49199,427,2,3,0,1,1],[49200,427,2,3,0,1,1],[49201,427,2,3,0,1,1],[49202,427,2,3,0,1,1],[49203,427,2,3,0,1,1],[49204,427,2,3,0,1,1],[49205,427,2,3,0,1,1],[49206,427,2,3,0,1,1],[49207,427,2,3,0,1,1],[49208,427,2,3,0,1,1],[49209,427,2,3,0,1,1],[49210,427,2,3,0,1,1],[49211,427,2,3,0,1,1],[49212,427,2,3,0,1,1],[49213,427,2,3,0,1,1],[49214,427,2,3,0,1,1],[49215,427,2,3,0,1,1],[49216,427,2,3,0,1,1],[49217,427,2,3,0,1,1],[49218,427,2,3,0,1,1],[49219,427,2,3,0,1,1],[49256,315,23,1,5,1,1],[49260,346,1,1,4,3,1],[49261,107,1,2,0,4,1],[49262,107,1,2,0,4,1],[49263,142,1,5,0,3,1],[49264,141,1,4,0,3,1],[49279,427,2,3,0,1,1],[49280,427,2,3,0,1,1],[49281,427,2,3,0,1,1],[49282,427,2,3,0,1,1],[49283,427,2,3,0,1,1],[49284,427,2,3,0,1,1],[49285,427,2,3,0,1,1],[49286,427,2,3,0,1,1],[49287,427,2,3,0,1,1],[49288,427,2,3,0,1,1],[49289,427,2,3,0,1,1],[49290,427,2,3,0,1,1],[49291,427,2,3,0,1,1],[49292,427,2,3,0,1,1],[49293,427,2,3,0,1,1],[49294,427,2,3,0,1,1],[49295,427,2,3,0,1,1],[49296,427,2,3,0,1,1],[49297,427,2,3,0,1,1],[49298,427,2,3,0,1,1],[49299,427,2,3,0,1,1],[49300,427,2,3,0,1,1],[49301,427,2,3,0,1,1],[49302,427,2,3,0,1,1],[49303,427,2,3,0,1,1],[49304,427,2,3,0,1,1],[49305,427,2,3,0,1,1],[49306,427,2,3,0,1,1],[49307,427,2,3,0,1,1],[49308,427,2,3,0,1,1],[49309,427,2,3,0,1,1],[49310,427,2,3,0,1,1],[49311,427,2,3,0,1,1],[49312,427,2,3,0,1,1],[49313,427,2,3,0,1,1],[49314,427,2,3,0,1,1],[49315,114,23,5,0,3,1],[49317,596,23,2,0,1,1],[49319,264,23,1,2,1,1],[49321,550,23,2,0,2,1],[49322,264,23,1,2,1,1],[49323,114,23,9,0,2,1],[49324,316,23,1,5,1,1],[49325,317,23,2,0,2,1],[49330,278,23,2,0,3,2],[49332,27,26,3,0,1,2],[49333,190,38,3,0,4,2],[49336,146,15,23,0,3,2],[49338,315,23,1,5,1,1],[49383,65,23,1,3,4,1],[49384,65,23,1,3,4,1],[49387,117,23,1,21,3,1],[49390,65,23,1,5,4,1],[49391,65,23,1,5,4,1],[49392,65,23,1,5,4,1],[49395,146,15,9,0,3,1],[49396,577,15,2,0,2,1],[49397,50,15,2,0,2,1],[49398,166,15,9,0,1,1],[49399,657,15,2,0,1,1],[49400,268,15,9,0,2,1],[49402,339,15,2,0,2,1],[49403,41,15,2,0,2,1],[49464,106,38,1,3,4,1],[49465,106,38,1,3,4,1],[49466,106,38,1,3,4,1],[49469,75,1,1,5,1,1],[49470,75,1,1,5,1,1],[49492,224,23,1,5,3,3],[49495,227,23,1,7,3,1],[49501,88,23,2,0,3,1],[49503,61,17,1,20,4,3],[49505,509,23,3,0,1,2],[49809,11,8,11,0,1,4],[49810,11,8,11,0,1,4],[49812,590,23,1,1,2,1],[49813,60,23,2,0,2,1],[49814,60,23,10,0,2,1],[49815,319,23,1,5,1,1],[49816,319,23,1,5,1,1],[49817,558,1,9,0,4,2],[49818,350,1,2,0,4,2],[49949,75,1,1,5,1,1],[49950,75,1,1,5,1,1],[49954,141,1,5,0,3,1],[49961,88,23,1,3,3,1],[49962,88,23,1,3,3,1],[50001,202,17,3,0,1,2],[50002,202,17,3,0,1,2],[50005,322,23,3,0,3,2],[50212,614,25,3,0,1,2],[50319,293,2,3,0,1,2],[50321,88,23,2,0,3,2],[50322,88,23,2,0,3,2],[50469,427,2,3,0,1,1],[50470,427,2,3,0,1,1],[50471,427,2,3,0,1,1],[50472,427,2,3,0,1,1],[50473,427,2,3,0,1,1],[50474,427,2,3,0,1,1],[50475,427,2,3,0,1,1],[50476,427,2,3,0,1,1],[50477,427,2,3,0,1,1],[50478,427,2,3,0,1,1],[50479,427,2,3,0,1,1],[50480,427,2,3,0,1,1],[50481,427,2,3,0,1,1],[50482,427,2,3,0,1,1],[50483,427,2,3,0,1,1],[50484,427,2,3,0,1,1],[50485,427,2,3,0,1,1],[50486,427,2,3,0,1,1],[50487,427,2,3,0,1,1],[50488,427,2,3,0,1,1],[50489,427,2,3,0,1,1],[50490,427,2,3,0,1,1],[50491,427,2,3,0,1,1],[50492,427,2,3,0,1,1],[50493,427,2,3,0,1,1],[50494,427,2,3,0,1,1],[50495,427,2,3,0,1,1],[50496,427,2,3,0,1,1],[50497,427,2,3,0,1,1],[50498,427,2,3,0,1,1],[50499,427,2,3,0,1,1],[50500,427,2,3,0,1,1],[50501,427,2,3,0,1,1],[50502,427,2,3,0,1,1],[50503,427,2,3,0,1,1],[50504,427,2,3,0,1,1],[50986,617,1,1,7,1,1],[50992,164,1,1,5,1,1],[50993,164,1,1,5,1,1],[50995,371,72,1,2,3,1],[50996,164,1,1,5,1,1],[50997,164,1,1,5,1,1],[50998,574,6,3,8,1,1],[50999,248,1,1,23,1,1],[51000,164,1,1,5,1,1],[51002,329,20,3,0,1,1],[51003,164,1,1,5,1,1],[51004,164,1,1,5,1,1],[51005,164,1,1,5,1,1],[51006,164,1,1,5,1,1],[51007,164,1,1,5,1,1],[51008,290,3,1,12,1,1],[51009,164,1,1,5,1,1],[51010,164,1,1,5,1,1],[51011,164,1,1,5,1,1],[51013,618,2,2,0,1,1],[51014,498,6,2,0,2,1],[51015,164,1,1,5,1,1],[51016,164,1,1,5,1,1],[51017,164,1,1,5,1,1],[51018,164,1,1,5,1,1],[51019,574,6,3,8,1,1],[51020,164,1,1,5,1,1],[51021,352,1,1,35,1,1],[51022,352,1,1,35,1,1],[51023,164,1,1,5,1,1],[51024,164,1,1,5,1,1],[51026,164,1,1,5,1,1],[51027,164,1,1,5,1,1],[51028,164,1,1,5,1,1],[51029,164,1,1,5,1,1],[51030,513,85,1,49,3,1],[51031,492,89,3,8,2,1],[51032,618,2,2,0,1,1],[51033,574,6,3,8,1,1],[51035,164,1,1,5,1,1],[51036,352,1,1,35,1,1],[51037,164,1,1,5,1,1],[51038,371,72,1,2,3,1],[51039,164,1,1,5,1,1],[51040,164,1,1,5,1,1],[51041,164,1,1,5,1,1],[51042,164,1,1,5,1,1],[51043,164,1,1,5,1,1],[51045,164,1,1,5,1,1],[51046,164,1,1,5,1,1],[51047,164,1,1,5,1,1],[51048,164,1,1,5,1,1],[51049,164,1,1,5,1,1],[51050,371,72,1,2,3,1],[51051,329,20,3,0,1,1],[51052,164,1,1,5,1,1],[51054,352,1,1,35,1,1],[51056,164,1,1,5,1,1],[51057,329,20,3,0,1,1],[51058,352,1,1,35,1,1],[51059,329,20,3,0,1,1],[51062,574,6,3,8,1,1],[51063,574,6,3,8,1,1],[51064,164,1,1,5,1,1],[51065,164,1,1,5,1,1],[51066,164,1,1,5,1,1],[51068,574,6,3,8,1,1],[51069,618,2,2,0,1,1],[51070,290,3,1,12,1,1],[51071,94,1,1,12,1,1],[51072,94,1,1,12,1,1],[51073,574,6,3,8,1,1],[51075,8,1,2,0,4,1],[51077,8,1,2,0,4,1],[51082,618,2,2,0,1,1],[51083,574,6,3,8,1,1],[51084,163,1,2,0,11,1],[51087,557,95,1,0,1,1],[51088,557,95,1,0,1,1],[51094,441,1,2,0,3,1],[51095,576,1,2,0,3,1],[51096,441,1,2,0,3,1],[51097,231,1,3,0,5,1],[51098,557,95,1,0,1,1],[51099,555,94,2,0,1,1],[51102,88,23,2,0,3,1],[51280,255,1,21,24,4,2],[51281,255,1,21,24,4,2],[51284,363,23,1,38,3,1],[51444,134,45,1,7,7,1],[51445,8,1,1,5,4,1],[51511,61,17,1,7,4,4],[51622,427,2,3,0,1,1],[51623,427,2,3,0,1,1],[51624,427,2,3,0,1,1],[51625,427,2,3,0,1,1],[51626,427,2,3,0,1,1],[51627,427,2,3,0,1,1],[51628,427,2,3,0,1,1],[51629,427,2,3,0,1,1],[51630,427,2,3,0,1,1],[51631,427,2,3,0,1,1],[51632,427,2,3,0,1,1],[51633,427,2,3,0,1,1],[51634,427,2,3,0,1,1],[51635,427,2,3,0,1,1],[51636,427,2,3,0,1,1],[51637,427,2,3,0,1,1],[51638,427,2,3,0,1,1],[51639,427,2,3,0,1,1],[51640,427,2,3,0,1,1],[51641,427,2,3,0,1,1],[51642,427,2,3,0,1,1],[51643,427,2,3,0,1,1],[51644,427,2,3,0,1,1],[51645,427,2,3,0,1,1],[51646,427,2,3,0,1,1],[51647,427,2,3,0,1,1],[51648,427,2,3,0,1,1],[51649,427,2,3,0,1,1],[51650,427,2,3,0,1,1],[51651,427,2,3,0,1,1],[51652,427,2,3,0,1,1],[51653,427,2,3,0,1,1],[51654,427,2,3,0,1,1],[51655,427,2,3,0,1,1],[51656,95,28,1,7,3,1],[51657,296,60,4,0,15,1],[51658,95,28,1,28,3,1],[51822,363,23,1,38,3,1],[51824,593,23,2,0,1,1],[51825,258,23,1,25,3,1],[51826,258,23,1,25,3,1],[51827,258,23,1,13,3,1],[51828,258,23,1,13,3,1],[51829,570,23,1,5,1,1],[51830,570,23,1,50,1,1],[51831,642,23,1,0,1,1],[51832,315,23,1,5,1,1],[51833,315,23,1,5,1,1],[51834,315,23,1,5,1,1],[51835,315,23,1,5,1,1],[51836,315,23,1,5,1,1],[51837,315,23,1,5,1,1],[51838,315,23,1,5,1,1],[51839,315,23,1,5,1,1],[51840,315,23,1,5,1,1],[51841,315,23,1,5,1,1],[51843,113,23,1,7,1,1],[51845,148,23,1,18,1,1],[51846,365,23,1,5,2,1],[51847,559,15,1,7,1,1],[51850,244,1,1,19,3,2],[51946,655,23,3,0,1,1],[51947,655,23,3,0,1,1],[51948,655,23,3,0,1,1],[51949,655,23,3,0,1,1],[51950,655,23,3,0,1,1],[51951,655,23,3,0,1,1],[51954,331,66,1,42,4,1],[52009,538,1,3,0,1,1],[52010,538,1,3,0,1,1],[52011,538,1,3,0,1,1],[52012,538,1,3,0,1,1],[52013,538,1,3,0,1,1],[52014,538,1,3,0,1,1],[52015,538,1,3,0,1,1],[52016,538,1,3,0,1,1],[52017,434,1,2,0,2,1],[52018,538,1,3,0,1,1],[52019,538,1,3,0,1,1],[52020,538,1,3,0,1,1],[52021,538,1,3,0,1,1],[52022,538,1,3,0,1,1],[52023,538,1,3,0,1,1],[52024,538,1,3,0,1,1],[52025,538,1,3,0,1,1],[52026,538,1,3,0,1,1],[52027,538,1,3,0,1,1],[52028,538,1,3,0,1,1],[52029,538,1,3,0,1,1],[52084,65,23,1,5,4,1],[52146,377,17,3,0,4,3],[52150,279,23,2,0,3,1],[52151,463,23,1,0,3,1],[52157,542,1,3,0,1,1],[52158,243,1,4,0,1,1],[52159,72,34,1,21,3,1],[52160,22,16,2,0,2,1],[52161,40,10,9,0,4,1],[52162,366,1,3,0,1,1],[52164,538,1,3,0,1,1],[52165,263,1,22,3,1,1],[52166,538,1,3,0,1,1],[52167,263,1,22,3,1,1],[52168,89,21,1,0,1,1],[52170,263,1,22,3,1,1],[52171,89,21,1,0,1,1],[52172,89,21,1,0,1,1],[52174,83,38,1,11,1,1],[52175,63,33,9,0,3,1],[52176,538,1,3,0,1,1],[52177,538,1,3,0,1,1],[52178,89,21,1,0,1,1],[52179,538,1,3,0,1,1],[52180,538,1,3,0,1,1],[52181,538,1,3,0,1,1],[52182,538,1,3,0,1,1],[52183,538,1,3,0,1,1],[52184,89,21,1,0,1,1],[52185,538,1,3,0,1,1],[52186,538,1,3,0,1,1],[52187,538,1,3,0,1,1],[52188,452,84,2,0,15,1],[52189,340,26,1,0,1,1],[52190,340,26,1,0,1,1],[52191,561,84,4,0,2,1],[52192,561,84,4,0,2,1],[52193,340,26,1,0,1,1],[52194,340,26,1,0,1,1],[52196,75,1,1,5,1,1],[52197,75,1,1,5,1,1],[52200,227,23,1,7,3,1],[52202,61,17,1,3,4,1],[52255,509,23,3,0,12,2],[52257,165,23,4,0,3,1],[52259,8,1,1,3,4,1],[52320,520,23,1,5,1,1],[52322,520,23,1,5,1,1],[52388,315,23,1,5,1,1],[52389,315,23,1,5,1,1],[52390,315,23,1,5,1,1],[52391,315,23,1,5,1,1],[52392,315,23,1,5,1,1],[52394,538,1,3,0,1,1],[52395,538,1,3,0,1,1],[52396,538,1,3,0,1,1],[52397,538,1,3,0,1,1],[52398,538,1,3,0,1,1],[52399,538,1,3,0,1,1],[52400,538,1,3,0,1,1],[52401,538,1,3,0,1,1],[52402,538,1,3,0,1,1],[52403,538,1,3,0,1,1],[52404,538,1,3,0,1,1],[52405,538,1,3,0,1,1],[52406,538,1,3,0,1,1],[52407,538,1,3,0,1,1],[52408,538,1,3,0,1,1],[52409,538,1,3,0,1,1],[52410,538,1,3,0,1,1],[52411,538,1,3,0,1,1],[52412,538,1,3,0,1,1],[52413,538,1,3,0,1,1],[52414,538,1,3,0,1,1],[52415,538,1,3,0,1,1],[52416,538,1,3,0,1,1],[52417,538,1,3,0,1,1],[52418,610,34,2,0,1,1],[52419,392,1,2,0,1,1],[52420,610,34,2,0,1,1],[52422,83,38,1,11,1,1],[52423,170,1,2,0,1,1],[52424,170,1,2,0,1,1],[52426,170,1,2,0,1,1],[52443,315,23,1,5,1,1],[52444,315,23,1,5,1,1],[52445,315,23,1,5,1,1],[52446,315,23,1,5,1,1],[52447,315,23,1,5,1,1],[52448,315,23,1,5,1,1],[52449,315,23,1,5,1,1],[52450,315,23,1,5,1,1],[52713,61,17,1,3,4,1],[52732,352,1,1,35,1,1],[52733,352,1,1,35,1,1],[52735,119,1,1,6,1,1],[52736,352,1,1,35,1,1],[52741,119,1,1,6,1,1],[52747,89,21,1,0,1,1],[52748,89,21,1,0,1,1],[52749,290,3,1,7,1,1],[52752,89,21,1,0,1,1],[52755,290,3,1,7,1,1],[52758,290,3,1,7,1,1],[52759,290,3,1,7,1,1],[52762,290,3,1,7,1,1],[52764,89,21,1,0,1,1],[52769,352,1,1,35,1,1],[52785,233,23,19,0,1,1],[52786,233,23,19,0,1,1],[52787,233,23,19,0,1,1],[52788,233,23,19,0,1,1],[52789,233,23,19,0,1,1],[52790,233,23,19,0,1,1],[52791,233,23,19,0,1,1],[52792,233,23,19,0,1,1],[52793,233,23,19,0,1,1],[52817,409,48,3,0,3,2],[52887,496,34,1,7,4,1],[52888,241,1,3,0,1,1],[52889,8,1,10,0,4,1],[52890,8,1,10,0,4,1],[52891,8,1,10,0,4,1],[52892,8,1,10,0,4,1],[52894,465,18,9,0,3,1],[52897,336,18,1,5,2,1],[52898,478,18,1,21,2,1],[52899,530,18,9,0,2,1],[52901,600,23,5,0,1,1],[52903,95,28,3,0,3,2],[52904,372,59,3,0,1,2],[52907,65,23,1,0,4,1],[52908,65,23,1,0,4,1],[52909,65,23,1,0,4,1],[52912,224,23,1,7,3,1],[52933,27,26,3,0,1,2],[52935,167,30,1,5,4,1],[52937,403,78,1,0,1,1],[52941,350,1,2,0,4,1],[52942,350,1,2,0,4,2],[52984,61,17,11,0,5,4],[53100,322,23,3,0,3,2],[53102,8,1,1,0,4,1],[53128,520,23,1,7,1,1],[53129,520,23,1,7,1,1],[53316,65,23,1,5,4,1],[53318,65,23,1,5,4,1],[53352,8,1,2,0,4,1],[53355,9,1,1,1,4,2],[53370,331,66,1,5,4,1],[53371,459,17,2,0,2,1],[53372,459,17,2,0,2,1],[53586,117,23,2,0,3,1],[53698,65,23,1,7,4,1],[53757,635,23,3,52,1,1],[53758,635,23,3,52,1,1],[53760,88,23,1,0,4,1],[53761,88,23,1,0,4,1],[53763,88,23,1,0,4,1],[53765,13,5,3,0,1,2],[53808,77,1,3,0,1,1],[53813,509,23,3,0,1,2],[53815,559,15,1,7,1,1],[53876,117,23,2,0,3,1],[53877,463,23,1,4,3,1],[53883,8,1,1,5,4,1],[53884,88,23,2,0,3,1],[53885,88,23,2,0,3,1],[53943,65,23,1,5,4,1],[53946,65,23,1,5,4,1],[53947,65,23,1,5,4,1],[53948,463,23,2,0,3,1],[53949,510,23,2,0,3,1],[53950,463,23,2,0,3,1],[53960,27,26,3,0,1,2],[53961,27,26,3,0,1,2],[54020,634,23,2,0,3,1],[54021,634,23,2,0,3,1],[54026,221,1,3,0,1,2],[54027,221,1,3,0,1,2],[54029,117,23,5,0,3,1],[54031,61,17,11,0,5,4],[54033,34,19,3,0,3,1],[54035,285,23,1,0,3,1],[54042,65,23,1,5,4,1],[54043,65,23,1,5,4,1],[54045,65,23,1,5,4,1],[54048,13,5,3,0,1,2],[54109,61,17,22,0,4,1],[54110,61,17,22,0,4,1],[54113,427,2,3,0,1,1],[54114,427,2,3,0,1,1],[54115,427,2,3,0,1,1],[54116,427,2,3,0,1,1],[54117,427,2,3,0,1,1],[54118,427,2,3,0,1,1],[54119,427,2,3,0,1,1],[54120,427,2,3,0,1,1],[54121,427,2,3,0,1,1],[54122,427,2,3,0,1,1],[54123,427,2,3,0,1,1],[54124,427,2,3,0,1,1],[54125,427,2,3,0,1,1],[54126,427,2,3,0,1,1],[54127,427,2,3,0,1,1],[54128,427,2,3,0,1,1],[54129,427,2,3,0,1,1],[54130,427,2,3,0,1,1],[54131,427,2,3,0,1,1],[54132,427,2,3,0,1,1],[54133,427,2,3,0,1,1],[54134,427,2,3,0,1,1],[54135,427,2,3,0,1,1],[54136,427,2,3,0,1,1],[54137,427,2,3,0,1,1],[54138,427,2,3,0,1,1],[54139,427,2,3,0,1,1],[54140,427,2,3,0,1,1],[54141,427,2,3,0,1,1],[54142,427,2,3,0,1,1],[54143,427,2,3,0,1,1],[54144,427,2,3,0,1,1],[54145,427,2,3,0,1,1],[54146,427,2,3,0,1,1],[54147,427,2,3,0,1,1],[54148,427,2,3,0,1,1],[54225,13,5,3,0,1,2],[54642,427,2,3,0,1,1],[54643,427,2,3,0,1,1],[54644,427,2,3,0,1,1],[54645,427,2,3,0,1,1],[54646,427,2,3,0,1,1],[54647,427,2,3,0,1,1],[54648,427,2,3,0,1,1],[54649,427,2,3,0,1,1],[54650,427,2,3,0,1,1],[54651,427,2,3,0,1,1],[54652,427,2,3,0,1,1],[54653,427,2,3,0,1,1],[54654,427,2,3,0,1,1],[54655,427,2,3,0,1,1],[54656,427,2,3,0,1,1],[54657,427,2,3,0,1,1],[54658,427,2,3,0,1,1],[54659,427,2,3,0,1,1],[54660,427,2,3,0,1,1],[54661,427,2,3,0,1,1],[54662,427,2,3,0,1,1],[54663,427,2,3,0,1,1],[54664,427,2,3,0,1,1],[54665,427,2,3,0,1,1],[54666,427,2,3,0,1,1],[54667,427,2,3,0,1,1],[54668,427,2,3,0,1,1],[54669,427,2,3,0,1,1],[54670,427,2,3,0,1,1],[54671,427,2,3,0,1,1],[54672,427,2,3,0,1,1],[54673,427,2,3,0,1,1],[54674,427,2,3,0,1,1],[54675,427,2,3,0,1,1],[54676,427,2,3,0,1,1],[54677,427,2,3,0,1,1],[54678,427,2,3,0,1,1],[54679,427,2,3,0,1,1],[54680,427,2,3,0,1,1],[54681,427,2,3,0,1,1],[54940,358,23,5,36,2,1],[55009,554,93,9,0,1,1],[55010,374,11,1,39,1,1],[55011,83,38,1,11,1,1],[55012,129,25,3,16,1,1],[55013,352,26,1,35,1,1],[55014,352,26,1,35,1,1],[55015,71,10,1,9,4,1],[55017,352,26,1,35,1,1],[55018,340,26,1,0,1,1],[55019,340,26,1,0,1,1],[55020,164,1,1,5,1,1],[55021,164,1,1,5,1,1],[55022,164,1,1,5,1,1],[55023,164,1,1,5,1,1],[55024,164,1,1,5,1,1],[55025,164,1,1,5,1,1],[55026,164,1,1,5,1,1],[55027,164,1,1,5,1,1],[55028,164,1,1,5,1,1],[55029,164,1,1,5,1,1],[55030,164,1,1,5,1,1],[55031,164,1,1,5,1,1],[55032,164,1,1,5,1,1],[55033,164,1,1,5,1,1],[55034,366,1,3,0,1,1],[55035,164,1,1,5,1,1],[55036,617,1,1,7,1,1],[55037,352,26,1,35,1,1],[55038,352,26,1,35,1,1],[55039,164,1,1,5,1,1],[55040,164,1,1,5,1,1],[55041,524,39,9,0,1,1],[55042,164,1,1,5,1,1],[55043,164,1,1,5,1,1],[55044,556,4,1,2,1,1],[55045,89,21,1,0,1,1],[55046,366,1,3,0,1,1],[55047,89,21,1,0,1,1],[55048,89,21,1,0,1,1],[55049,290,3,1,7,1,1],[55050,617,1,1,7,1,1],[55052,524,39,9,0,1,1],[55053,186,1,1,13,1,1],[55054,524,39,9,0,1,1],[55055,164,1,1,5,1,1],[55056,629,1,2,0,1,1],[55057,164,1,1,5,1,1],[55058,524,39,9,0,1,1],[55061,524,39,9,0,1,1],[55062,290,3,1,7,1,1],[55063,164,1,1,5,1,1],[55064,89,21,1,0,1,1],[55065,164,1,1,5,1,1],[55066,164,1,1,5,1,1],[55067,421,6,2,0,1,1],[55068,164,1,1,5,1,1],[55069,164,1,1,5,1,1],[55070,164,1,1,5,1,1],[55071,164,1,1,5,1,1],[55072,553,15,5,0,1,1],[55073,574,6,5,0,2,1],[55074,164,1,1,5,1,1],[55075,164,1,1,5,1,1],[55076,651,1,9,0,1,1],[55077,164,1,1,5,1,1],[55078,164,1,1,5,1,1],[55079,164,1,1,5,1,1],[55080,164,1,1,5,1,1],[55081,458,85,2,0,2,1],[55082,164,1,1,5,1,1],[55083,164,1,1,5,1,1],[55084,223,38,2,0,1,1],[55085,340,26,1,0,1,1],[55086,340,26,1,0,1,1],[55087,538,1,3,0,1,1],[55088,352,26,1,35,1,1],[55089,538,1,3,0,1,1],[55090,115,21,9,0,1,1],[55091,538,1,3,0,1,1],[55092,538,1,3,0,1,1],[55093,71,10,1,9,4,1],[55094,538,1,3,0,1,1],[55095,538,1,3,0,1,1],[55096,538,1,3,0,1,1],[55097,538,1,3,0,1,1],[55098,63,33,3,8,2,1],[55099,538,1,3,0,1,1],[55100,538,1,3,0,1,1],[55101,538,1,3,0,1,1],[55102,538,1,3,0,1,1],[55103,342,68,2,0,2,1],[55107,2,2,1,2,1,1],[55108,659,30,2,0,1,1],[55133,315,23,2,26,1,1],[55134,592,23,28,0,1,1],[55135,592,23,28,0,1,1],[55136,593,23,2,0,1,1],[55137,396,23,2,0,2,1],[55138,583,1,2,0,4,2],[55140,427,2,3,0,1,1],[55141,427,2,3,0,1,1],[55142,427,2,3,0,1,1],[55143,427,2,3,0,1,1],[55144,427,2,3,0,1,1],[55145,427,2,3,0,1,1],[55146,427,2,3,0,1,1],[55147,427,2,3,0,1,1],[55148,427,2,3,0,1,1],[55149,427,2,3,0,1,1],[55150,427,2,3,0,1,1],[55151,427,2,3,0,1,1],[55152,427,2,3,0,1,1],[55153,427,2,3,0,1,1],[55154,427,2,3,0,1,1],[55155,427,2,3,0,1,1],[55156,427,2,3,0,1,1],[55157,427,2,3,0,1,1],[55158,427,2,3,0,1,1],[55159,427,2,3,0,1,1],[55160,427,2,3,0,1,1],[55161,427,2,3,0,1,1],[55162,427,2,3,0,1,1],[55163,427,2,3,0,1,1],[55164,427,2,3,0,1,1],[55165,427,2,3,0,1,1],[55166,427,2,3,0,1,1],[55167,427,2,3,0,1,1],[55168,427,2,3,0,1,1],[55169,427,2,3,0,1,1],[55239,37,23,3,0,1,2],[55242,512,23,2,0,3,1],[55243,512,23,2,0,3,1],[55244,65,23,1,5,4,1],[55248,468,23,1,5,3,1],[55249,468,23,1,5,3,1],[55250,365,23,1,5,2,1],[55251,315,23,1,5,1,1],[55252,315,23,1,5,1,1],[55253,315,23,1,5,1,1],[55254,315,23,1,5,1,1],[55255,315,23,1,5,1,1],[55256,315,23,1,5,1,1],[55257,68,23,1,7,1,1],[55258,318,23,1,5,1,1],[55259,318,23,1,5,1,1],[55260,318,23,1,5,1,1],[55261,604,23,2,0,3,1],[55263,9,1,3,0,4,2],[55264,350,1,2,0,4,2],[55268,399,1,11,0,5,4],[55324,263,1,22,3,1,1],[55326,263,1,22,3,1,1],[55327,263,1,22,3,1,1],[55329,291,15,1,7,3,1],[55506,180,17,1,6,3,2],[55508,25,11,3,0,1,2],[55562,95,28,9,0,3,1],[55683,293,2,3,0,1,2],[55686,509,23,3,0,1,2],[55690,281,48,1,26,3,1],[55801,427,2,3,0,1,1],[55802,427,2,3,0,1,1],[55803,427,2,3,0,1,1],[55804,427,2,3,0,1,1],[55805,427,2,3,0,1,1],[55806,427,2,3,0,1,1],[55807,427,2,3,0,1,1],[55808,427,2,3,0,1,1],[55809,427,2,3,0,1,1],[55810,427,2,3,0,1,1],[55811,427,2,3,0,1,1],[55812,427,2,3,0,1,1],[55813,427,2,3,0,1,1],[55814,427,2,3,0,1,1],[55815,427,2,3,0,1,1],[55816,427,2,3,0,1,1],[55817,427,2,3,0,1,1],[55818,427,2,3,0,1,1],[55819,427,2,3,0,1,1],[55820,427,2,3,0,1,1],[55821,427,2,3,0,1,1],[55822,427,2,3,0,1,1],[55823,427,2,3,0,1,1],[55824,427,2,3,0,1,1],[55825,427,2,3,0,1,1],[55826,427,2,3,0,1,1],[55827,427,2,3,0,1,1],[55828,427,2,3,0,1,1],[55829,427,2,3,0,1,1],[55830,427,2,3,0,1,1],[55836,322,23,1,5,3,1],[55839,322,23,1,5,3,1],[55841,361,17,3,0,3,2],[55844,281,48,1,26,3,1],[55861,511,23,2,0,3,1],[55909,94,1,1,12,1,1],[55910,94,1,1,12,1,1],[55912,224,23,1,5,3,2],[55970,27,26,3,0,1,2],[55971,27,26,3,0,1,2],[55973,592,23,28,0,1,1],[55974,592,23,28,0,1,1],[55975,592,23,28,0,1,1],[55976,592,23,28,0,1,1],[55978,61,17,1,3,4,1],[55982,75,1,1,5,1,1],[55983,75,1,1,5,1,1],[56055,427,2,3,0,1,1],[56056,427,2,3,0,1,1],[56057,427,2,3,0,1,1],[56058,427,2,3,0,1,1],[56059,427,2,3,0,1,1],[56060,427,2,3,0,1,1],[56061,427,2,3,0,1,1],[56062,427,2,3,0,1,1],[56063,427,2,3,0,1,1],[56064,427,2,3,0,1,1],[56065,427,2,3,0,1,1],[56066,427,2,3,0,1,1],[56067,427,2,3,0,1,1],[56068,427,2,3,0,1,1],[56069,427,2,3,0,1,1],[56070,427,2,3,0,1,1],[56071,427,2,3,0,1,1],[56072,427,2,3,0,1,1],[56073,427,2,3,0,1,1],[56074,427,2,3,0,1,1],[56075,427,2,3,0,1,1],[56076,427,2,3,0,1,1],[56077,427,2,3,0,1,1],[56078,427,2,3,0,1,1],[56079,427,2,3,0,1,1],[56080,427,2,3,0,1,1],[56081,427,2,3,0,1,1],[56083,61,6,1,7,4,1],[56091,61,17,14,0,4,1],[56153,277,39,1,7,1,1],[56154,277,39,1,7,1,1],[56155,277,39,1,7,1,1],[56156,277,39,1,7,1,1],[56157,65,23,1,7,4,1],[56162,62,1,9,0,4,1],[56163,62,1,9,0,4,1],[56164,62,1,9,0,4,1],[56165,62,1,9,0,4,1],[56166,62,1,9,0,4,1],[56167,62,1,9,0,4,1],[56168,62,1,9,0,4,1],[56169,62,1,9,0,4,1],[56170,62,1,9,0,4,1],[56171,62,1,9,0,4,1],[56174,221,1,3,0,1,2],[56178,292,25,1,13,2,1],[56179,84,2,2,0,1,1],[56180,153,12,1,5,3,1],[56181,332,25,3,2,10,1],[56182,352,1,1,35,1,1],[56183,497,1,3,30,1,1],[56184,551,5,2,0,2,1],[56185,83,38,1,11,1,1],[56186,239,20,4,0,1,1],[56187,7,7,4,0,2,1],[56188,122,1,5,0,2,1],[56189,308,1,2,0,1,1],[56190,89,21,1,0,1,1],[56191,263,1,22,3,1,1],[56193,263,1,22,3,1,1],[56194,417,10,1,2,3,1],[56195,240,1,1,21,1,1],[56196,629,1,2,0,1,1],[56197,240,1,1,21,1,1],[56198,617,1,1,7,1,1],[56199,608,1,2,51,1,1],[56201,89,21,1,0,1,1],[56202,89,21,1,0,1,1],[56203,89,21,1,0,1,1],[56204,239,20,4,0,1,1],[56205,205,52,1,5,4,1],[56206,352,1,1,35,1,1],[56207,568,97,1,13,3,1],[56208,455,38,2,0,1,1],[56209,239,20,4,0,1,1],[56210,129,25,1,13,1,1],[56211,297,38,14,0,3,1],[56212,489,88,2,0,2,1],[56213,494,1,1,5,2,1],[56214,344,9,3,30,1,1],[56215,624,16,9,0,1,1],[56216,183,38,9,0,1,1],[56217,329,20,3,0,1,1],[56218,329,20,3,0,1,1],[56219,12,1,4,0,1,1],[56220,12,1,4,0,1,1],[56221,304,44,5,0,3,1],[56222,158,4,5,0,2,1],[56223,631,86,9,0,1,1]]} diff --git a/src/data/ucsSatellites.js b/src/data/ucsSatellites.js index e3c67a2e2..5a87a2bd4 100644 --- a/src/data/ucsSatellites.js +++ b/src/data/ucsSatellites.js @@ -1,6 +1,6 @@ /** - * @file The bundled UCS Satellite Database pack: the purpose of each active - * satellite, keyed by NORAD catalog number. + * @file The bundled UCS Satellite Database pack: operator, owner country and + * purpose for active satellites, keyed by NORAD catalog number. * * Data: `local_data/ucs_satellites/ucs_satellites.json`, built by * `scripts/build-ucs-satellites.py` from UCS-Satellite-Database 5-1-2023 @@ -20,8 +20,11 @@ const PACK_URL = new URL( ); /** - * One UCS row: what UCS says a satellite is for. - * @typedef {{noradId: number, purpose: string|null}} UcsSatellite + * One UCS row: what UCS says about a satellite's operator and purpose. + * @typedef {{noradId: number, operator: string|null, + * operatorCountry: string|null, purpose: string|null, + * detailedPurpose: string|null, users: string|null, + * orbitClass: string|null}} UcsSatellite */ /** diff --git a/src/data/ucsSatellites.test.mjs b/src/data/ucsSatellites.test.mjs index 3b52a4e92..86df68e81 100644 --- a/src/data/ucsSatellites.test.mjs +++ b/src/data/ucsSatellites.test.mjs @@ -22,7 +22,15 @@ test('the bundled UCS pack names its release, licence and curation', () => { pack.meta.curation.invalidNoradDropped + pack.meta.curation.duplicateNoradDropped, ); - assert.deepEqual(pack.fields, ['noradId', 'purpose']); + assert.deepEqual(pack.fields, [ + 'noradId', + 'operator', + 'operatorCountry', + 'purpose', + 'detailedPurpose', + 'users', + 'orbitClass', + ]); // Small enough to load with the layer. assert.ok(readFileSync(PACK_URL).length < 200_000); }); @@ -33,26 +41,36 @@ test('the pack loads into records keyed by NORAD number', async () => { const iss = records.get(25544); assert.ok(iss, 'the ISS is in UCS'); assert.equal(iss.noradId, 25544); + assert.ok(iss.operator); assert.ok(iss.purpose); + for (const record of records.values()) { + assert.doesNotMatch( + `${record.operator ?? ''} ${record.purpose ?? ''}`, + /starlink/i, + 'Starlink rows are dropped', + ); + if (record.orbitClass) assert.match(record.orbitClass, /^(LEO|MEO|GEO|ELLIPTICAL)$/); + } }); test('indexing reads the string tables and turns empty strings into null', () => { const records = indexUcsPack({ - fields: ['noradId', 'purpose'], - strings: { purpose: ['', 'Earth Observation'] }, + fields: ['noradId', 'operator', 'purpose'], + strings: { operator: ['', 'ESA'], purpose: ['', 'Earth Observation'] }, records: [ - [39634, 1], - [40000, 0], - ['bad', 1], - [-5, 1], + [39634, 1, 1], + [40000, 0, 1], + ['bad', 1, 1], + [-5, 1, 1], ], }); assert.deepEqual([...records.keys()], [39634, 40000]); assert.deepEqual(records.get(39634), { noradId: 39634, + operator: 'ESA', purpose: 'Earth Observation', }); - assert.equal(records.get(40000).purpose, null); + assert.equal(records.get(40000).operator, null); }); test('a pack of the wrong shape throws, so the loader tries again', () => { diff --git a/src/layers/satellites/catalog.js b/src/layers/satellites/catalog.js index a7fd060a5..bb20e646a 100644 --- a/src/layers/satellites/catalog.js +++ b/src/layers/satellites/catalog.js @@ -124,6 +124,8 @@ export function createCatalog({ state: layerState, services, parts, source }) { satrec, group: 'dense', launchYear: tleLineLaunchYear(entry.line1), + line1: entry.line1, + line2: entry.line2, // The dense feed is CelesTrak's Starlink group. satelliteClass: 'starlink', ucs: null, diff --git a/src/layers/satellites/classes.js b/src/layers/satellites/classes.js index dea3dcc38..f4d47a0ea 100644 --- a/src/layers/satellites/classes.js +++ b/src/layers/satellites/classes.js @@ -231,6 +231,13 @@ export function classifySatellite({ return 'probes'; } +/** Whether a class may be ridden in the Cockpit's orbital view. */ +export function satelliteClassEnterable(satelliteClass) { + return ( + SATELLITE_CLASS_IDS.includes(satelliteClass) && satelliteClass !== 'debris' + ); +} + /** * Merge a partial class-visibility request into the current choice. * Unknown keys and non-boolean values are ignored. @@ -250,6 +257,443 @@ export function mergeClassVisibility( return next; } +// ISO 3166-1 alpha-2 code → short English name, for every owner below. +const COUNTRY_NAMES = Object.freeze({ + AE: 'United Arab Emirates', + AM: 'Armenia', + AO: 'Angola', + AR: 'Argentina', + AT: 'Austria', + AU: 'Australia', + AZ: 'Azerbaijan', + BD: 'Bangladesh', + BE: 'Belgium', + BG: 'Bulgaria', + BH: 'Bahrain', + BM: 'Bermuda', + BO: 'Bolivia', + BR: 'Brazil', + BT: 'Bhutan', + BW: 'Botswana', + BY: 'Belarus', + CA: 'Canada', + CH: 'Switzerland', + CL: 'Chile', + CN: 'China', + CO: 'Colombia', + CR: 'Costa Rica', + CZ: 'Czechia', + DE: 'Germany', + DJ: 'Djibouti', + DK: 'Denmark', + DZ: 'Algeria', + EC: 'Ecuador', + EE: 'Estonia', + EG: 'Egypt', + ES: 'Spain', + ET: 'Ethiopia', + FI: 'Finland', + FR: 'France', + GB: 'United Kingdom', + GH: 'Ghana', + GR: 'Greece', + GT: 'Guatemala', + HR: 'Croatia', + HU: 'Hungary', + ID: 'Indonesia', + IE: 'Ireland', + IL: 'Israel', + IN: 'India', + IQ: 'Iraq', + IR: 'Iran', + IT: 'Italy', + JO: 'Jordan', + JP: 'Japan', + KE: 'Kenya', + KP: 'North Korea', + KR: 'South Korea', + KW: 'Kuwait', + KZ: 'Kazakhstan', + LA: 'Laos', + LK: 'Sri Lanka', + LT: 'Lithuania', + LU: 'Luxembourg', + MA: 'Morocco', + MC: 'Monaco', + MD: 'Moldova', + ME: 'Montenegro', + MM: 'Myanmar', + MN: 'Mongolia', + MU: 'Mauritius', + MX: 'Mexico', + MY: 'Malaysia', + NG: 'Nigeria', + NL: 'Netherlands', + NO: 'Norway', + NP: 'Nepal', + NZ: 'New Zealand', + PE: 'Peru', + PH: 'Philippines', + PK: 'Pakistan', + PL: 'Poland', + PT: 'Portugal', + PY: 'Paraguay', + QA: 'Qatar', + RO: 'Romania', + RU: 'Russia', + RW: 'Rwanda', + SA: 'Saudi Arabia', + SB: 'Solomon Islands', + SD: 'Sudan', + SE: 'Sweden', + SG: 'Singapore', + SI: 'Slovenia', + SN: 'Senegal', + TH: 'Thailand', + TM: 'Turkmenistan', + TN: 'Tunisia', + TR: 'Türkiye', + TW: 'Taiwan', + UA: 'Ukraine', + US: 'United States', + UY: 'Uruguay', + VA: 'Vatican City', + VE: 'Venezuela', + VN: 'Vietnam', + ZA: 'South Africa', + ZW: 'Zimbabwe', +}); + +// UCS "Country of Operator/Owner" → ISO code. Joint owners ("USA/Japan") and +// organisations are not countries and resolve through ORGANISATIONS or as a +// joint label. +const UCS_COUNTRIES = Object.freeze({ + Algeria: 'DZ', + Angola: 'AO', + Argentina: 'AR', + Australia: 'AU', + Austria: 'AT', + Azerbaijan: 'AZ', + Bangladesh: 'BD', + Belarus: 'BY', + Belgium: 'BE', + Bolivia: 'BO', + Brazil: 'BR', + Bulgaria: 'BG', + Canada: 'CA', + Chile: 'CL', + China: 'CN', + Colombia: 'CO', + 'Czech Republic': 'CZ', + Denmark: 'DK', + Ecuador: 'EC', + Egypt: 'EG', + Estonia: 'EE', + Ethiopia: 'ET', + Finland: 'FI', + France: 'FR', + Germany: 'DE', + Greece: 'GR', + Hungary: 'HU', + India: 'IN', + Indonesia: 'ID', + Iran: 'IR', + Iraq: 'IQ', + Israel: 'IL', + Italy: 'IT', + Japan: 'JP', + Jordan: 'JO', + Kazakhstan: 'KZ', + Kenya: 'KE', + Kuwait: 'KW', + Laos: 'LA', + Lithuania: 'LT', + Luxembourg: 'LU', + Malaysia: 'MY', + Mexico: 'MX', + Monaco: 'MC', + Morocco: 'MA', + Nepal: 'NP', + Netherlands: 'NL', + 'New Zealand': 'NZ', + Nigeria: 'NG', + Norway: 'NO', + Pakistan: 'PK', + Peru: 'PE', + Poland: 'PL', + Russia: 'RU', + 'Saudi Arabia': 'SA', + Sinapore: 'SG', + Singapore: 'SG', + Slovenia: 'SI', + 'South Africa': 'ZA', + 'South Korea': 'KR', + Spain: 'ES', + Sudan: 'SD', + Sweden: 'SE', + Switzerland: 'CH', + Taiwan: 'TW', + Thailand: 'TH', + Tunisia: 'TN', + Turkey: 'TR', + UK: 'GB', + USA: 'US', + Ukraine: 'UA', + 'United Arab Emirates': 'AE', + 'United Kingdom': 'GB', + Venezuela: 'VE', + Vietnam: 'VN', +}); + +// CelesTrak SATCAT OWNER code → ISO code (https://celestrak.org/satcat/sources.php). +// CIS (former USSR) is filed under Russia, its continuing state. +const SATCAT_COUNTRIES = Object.freeze({ + ALG: 'DZ', + ANG: 'AO', + ARGN: 'AR', + ARM: 'AM', + ASRA: 'AT', + AUS: 'AU', + AZER: 'AZ', + BEL: 'BE', + BELA: 'BY', + BERM: 'BM', + BGD: 'BD', + BHR: 'BH', + BHUT: 'BT', + BOL: 'BO', + BRAZ: 'BR', + BUL: 'BG', + BWA: 'BW', + CA: 'CA', + CHLE: 'CL', + CIS: 'RU', + COL: 'CO', + CRI: 'CR', + CZCH: 'CZ', + DEN: 'DK', + DJI: 'DJ', + ECU: 'EC', + EGYP: 'EG', + EST: 'EE', + ETH: 'ET', + FIN: 'FI', + FR: 'FR', + GER: 'DE', + GHA: 'GH', + GREC: 'GR', + GUAT: 'GT', + HRV: 'HR', + HUN: 'HU', + IND: 'IN', + INDO: 'ID', + IRAN: 'IR', + IRAQ: 'IQ', + IRL: 'IE', + ISRA: 'IL', + ISRO: 'IN', + IT: 'IT', + JPN: 'JP', + KAZ: 'KZ', + KEN: 'KE', + LAOS: 'LA', + LKA: 'LK', + LTU: 'LT', + LUXE: 'LU', + MA: 'MA', + MALA: 'MY', + MCO: 'MC', + MDA: 'MD', + MEX: 'MX', + MMR: 'MM', + MNE: 'ME', + MNG: 'MN', + MUS: 'MU', + NETH: 'NL', + NIG: 'NG', + NKOR: 'KP', + NOR: 'NO', + NPL: 'NP', + NZ: 'NZ', + PAKI: 'PK', + PERU: 'PE', + POL: 'PL', + POR: 'PT', + PRC: 'CN', + PRY: 'PY', + QAT: 'QA', + ROC: 'TW', + ROM: 'RO', + RP: 'PH', + RWA: 'RW', + SAFR: 'ZA', + SAUD: 'SA', + SDN: 'SD', + SEN: 'SN', + SING: 'SG', + SKOR: 'KR', + SLB: 'SB', + SPN: 'ES', + SVN: 'SI', + SWED: 'SE', + SWTZ: 'CH', + THAI: 'TH', + TUN: 'TN', + TURK: 'TR', + UAE: 'AE', + UK: 'GB', + UKR: 'UA', + URY: 'UY', + US: 'US', + VAT: 'VA', + VENZ: 'VE', + VTNM: 'VN', + ZWE: 'ZW', +}); + +// Organisations, by SATCAT code and by UCS name: no flag, a short label. +const ORGANISATIONS = Object.freeze({ + AB: 'Arabsat', + ABS: 'ABS', + AC: 'AsiaSat', + ESA: 'ESA', + ESRO: 'ESRO', + EUME: 'EUMETSAT', + EUTE: 'Eutelsat', + GLOB: 'Globalstar', + IM: 'Inmarsat', + IRID: 'Iridium', + ISS: 'ISS partners', + ITSO: 'Intelsat', + NATO: 'NATO', + NICO: 'New ICO', + O3B: 'O3b', + ORB: 'ORBCOMM', + RASC: 'RascomStar-QAF', + SEAL: 'Sea Launch', + SES: 'SES', + Multinational: 'Multinational', +}); + +// SATCAT codes for joint ownership, as their parts. +const SATCAT_JOINT = Object.freeze({ + CHBZ: ['CN', 'BR'], + CHTU: ['CN', 'TR'], + FGER: ['FR', 'DE'], + FRIT: ['FR', 'IT'], + GRSA: ['GR', 'SA'], + PRES: ['CN', 'ESA'], + SGJP: ['SG', 'JP'], + STCT: ['SG', 'TW'], + TMMC: ['TM', 'MC'], + USBZ: ['US', 'BR'], +}); + +function country(code) { + return COUNTRY_NAMES[code] + ? { countryCode: code, label: COUNTRY_NAMES[code] } + : null; +} + +function joint(parts) { + const labels = parts.map( + (part) => COUNTRY_NAMES[part] || ORGANISATIONS[part] || part, + ); + return { countryCode: null, label: labels.join(' / ') }; +} + +/** + * Normalise a UCS owner country ("USA", "China/France", "ESA", + * "Multinational") to `{ countryCode, label }`. + * @param {string|null|undefined} text + * @returns {{countryCode: string|null, label: string}|null} + */ +export function ownerFromUcs(text) { + const value = String(text || '').trim(); + if (!value) return null; + if (UCS_COUNTRIES[value]) return country(UCS_COUNTRIES[value]); + if (ORGANISATIONS[value]) + return { countryCode: null, label: ORGANISATIONS[value] }; + if (value.includes('/')) + return joint( + value + .split('/') + .map((part) => part.trim()) + .map((part) => UCS_COUNTRIES[part] || part), + ); + return { countryCode: null, label: value }; +} + +/** + * Normalise a CelesTrak SATCAT OWNER code ("US", "PRC", "CIS", "ITSO") to + * `{ countryCode, label }`; null for TBD, UNK and blanks. + * @param {string|null|undefined} code + * @returns {{countryCode: string|null, label: string}|null} + */ +export function ownerFromSatcat(code) { + const value = String(code || '') + .trim() + .toUpperCase(); + if (!value || value === 'TBD' || value === 'UNK') return null; + if (SATCAT_COUNTRIES[value]) return country(SATCAT_COUNTRIES[value]); + if (ORGANISATIONS[value]) + return { countryCode: null, label: ORGANISATIONS[value] }; + if (SATCAT_JOINT[value]) return joint(SATCAT_JOINT[value]); + return null; +} + +/** + * Who owns a satellite: UCS names the operator's country, SATCAT the + * registering owner; UCS wins where both exist. Starlink without either is + * SpaceX's, so United States. + * @returns {{countryCode: string|null, label: string}|null} + */ +export function satelliteOwner({ + ucs = null, + satcat = null, + satelliteClass, +} = {}) { + return ( + ownerFromUcs(ucs?.operatorCountry) || + ownerFromSatcat(satcat?.owner) || + (satelliteClass === 'starlink' ? country('US') : null) + ); +} + +/** Who operates a satellite: UCS's operator, or SpaceX for Starlink. */ +export function satelliteOperator({ ucs = null, satelliteClass } = {}) { + if (ucs?.operator) return ucs.operator; + return satelliteClass === 'starlink' ? 'SpaceX' : null; +} + +/** + * The international designator (COSPAR id) from TLE line 1, columns 10–17: + * `98067A` → `1998-067A`. Two-digit years below 57 are 20xx. + * @param {string|null|undefined} line1 + * @returns {string|null} + */ +export function cosparIdFromTleLine1(line1) { + const field = String(line1 || '') + .slice(9, 17) + .trim(); + const match = /^(\d{2})(\d{3})([A-Z]{1,3})$/.exec(field); + if (!match) return null; + const yy = Number(match[1]); + return `${yy < 57 ? 2000 + yy : 1900 + yy}-${match[2]}${match[3]}`; +} + +/** + * The TLE's epoch as epoch milliseconds, from satellite.js's Julian date. + * @param {{jdsatepoch?: number, jdsatepochF?: number}|null|undefined} satrec + * @returns {number|null} + */ +export function tleEpochMs(satrec) { + const jd = Number(satrec?.jdsatepoch) + (Number(satrec?.jdsatepochF) || 0); + return Number.isFinite(jd) && jd > 0 + ? Math.round((jd - 2440587.5) * 86_400_000) + : null; +} + /** Split one RFC 4180 CSV line (quoted fields may hold commas). */ function csvFields(line) { const fields = []; @@ -277,7 +721,7 @@ function csvFields(line) { * Parse CelesTrak SATCAT CSV into records keyed by NORAD number. * @param {string} text `records.php?…&FORMAT=CSV` body. * @returns {Map} + * owner: string, cosparId: string|null, launchDate: string|null}>} */ export function parseSatcatCsv(text) { const records = new Map(); @@ -291,6 +735,8 @@ export function parseSatcatCsv(text) { norad: at('NORAD_CAT_ID'), type: at('OBJECT_TYPE'), status: at('OPS_STATUS_CODE'), + owner: at('OWNER'), + id: at('OBJECT_ID'), launch: at('LAUNCH_DATE'), }; if (col.norad < 0 || col.type < 0) return records; @@ -302,6 +748,8 @@ export function parseSatcatCsv(text) { records.set(noradId, { objectType: text(col.type).toUpperCase(), opsStatus: text(col.status), + owner: text(col.owner), + cosparId: text(col.id) || null, launchDate: text(col.launch) || null, }); } diff --git a/src/layers/satellites/classes.test.mjs b/src/layers/satellites/classes.test.mjs index 40346b949..6243181f9 100644 --- a/src/layers/satellites/classes.test.mjs +++ b/src/layers/satellites/classes.test.mjs @@ -1,20 +1,28 @@ import test from 'node:test'; import assert from 'node:assert/strict'; +import { twoline2satrec } from 'satellite.js'; import { DEFAULT_SATELLITE_CLASSES, PRESUMED_DEAD_AFTER_YEARS, SATELLITE_CLASS_DISPLAY, SATELLITE_CLASS_IDS, classifySatellite, + cosparIdFromTleLine1, mergeClassVisibility, + ownerFromSatcat, + ownerFromUcs, parseSatcatCsv, + satelliteClassEnterable, + satelliteOperator, + satelliteOwner, + tleEpochMs, } from './classes.js'; import { CATALOG_GROUPS } from './policy.js'; const NOW = 2026; const classify = (subject) => classifySatellite({ nowYear: NOW, ...subject }); -test('six classes, every one but Starlink on by default', () => { +test('six classes, with stations and imaging on by default and the rest off', () => { assert.deepEqual(SATELLITE_CLASS_IDS, [ 'stations', 'imaging', @@ -37,28 +45,16 @@ test('six classes, every one but Starlink on by default', () => { test('SATCAT object type and status file debris first, overruling UCS', () => { const imaging = { purpose: 'Earth Observation' }; for (const objectType of ['R/B', 'DEB', 'UNK']) - assert.equal( - classify({ name: 'X', satcat: { objectType, opsStatus: '' } }), - 'debris', - objectType, - ); + assert.equal(classify({ name: 'X', satcat: { objectType, opsStatus: '' } }), 'debris', objectType); // A satellite UCS listed in 2023 that SATCAT now calls dead or decayed. for (const opsStatus of ['-', 'D']) assert.equal( - classify({ - name: 'OLDSAT', - ucs: imaging, - satcat: { objectType: 'PAY', opsStatus }, - }), + classify({ name: 'OLDSAT', ucs: imaging, satcat: { objectType: 'PAY', opsStatus } }), 'debris', opsStatus, ); assert.equal( - classify({ - name: 'OLDSAT', - ucs: imaging, - satcat: { objectType: 'PAY', opsStatus: '+' }, - }), + classify({ name: 'OLDSAT', ucs: imaging, satcat: { objectType: 'PAY', opsStatus: '+' } }), 'imaging', ); // SATCAT calls a new launch's objects UNK until it names them: only an @@ -86,33 +82,15 @@ test('SATCAT object type and status file debris first, overruling UCS', () => { test('the ISS is a station whatever else says', () => { assert.equal( - classify({ - noradId: 25544, - name: 'ISS (ZARYA)', - group: 'visual', - satcat: { objectType: 'DEB' }, - }), + classify({ noradId: 25544, name: 'ISS (ZARYA)', group: 'visual', satcat: { objectType: 'DEB' } }), 'stations', ); }); test('stations: crewed stations and visiting vehicles by name', () => { - assert.equal( - classify({ name: 'CSS (TIANHE)', group: 'stations' }), - 'stations', - ); - assert.equal( - classify({ name: 'ISS (NAUKA)', group: 'stations' }), - 'stations', - ); - for (const name of [ - 'SHENZHOU-21', - 'TIANZHOU-9', - 'SOYUZ-MS 28', - 'PROGRESS-MS 31', - 'CREW DRAGON 11', - 'CYGNUS NG-23', - ]) + assert.equal(classify({ name: 'CSS (TIANHE)', group: 'stations' }), 'stations'); + assert.equal(classify({ name: 'ISS (NAUKA)', group: 'stations' }), 'stations'); + for (const name of ['SHENZHOU-21', 'TIANZHOU-9', 'SOYUZ-MS 28', 'PROGRESS-MS 31', 'CREW DRAGON 11', 'CYGNUS NG-23']) assert.equal(classify({ name, group: 'visual' }), 'stations', name); }); @@ -133,11 +111,7 @@ test('UCS purpose decides imaging, telecom and probes', () => { ['Unknown', 'probes'], ]; for (const [purpose, expected] of table) - assert.equal( - classify({ name: 'UNNAMED-1', group: 'visual', ucs: { purpose } }), - expected, - purpose, - ); + assert.equal(classify({ name: 'UNNAMED-1', group: 'visual', ucs: { purpose } }), expected, purpose); }); test('satellites launched after the UCS snapshot are classed by name', () => { @@ -156,42 +130,20 @@ test('satellites launched after the UCS snapshot are classed by name', () => { ['STARLINK-34012', 'starlink'], ]; for (const [name, expected] of table) - assert.equal( - classify({ name, group: 'visual', launchYear: 2025 }), - expected, - name, - ); + assert.equal(classify({ name, group: 'visual', launchYear: 2025 }), expected, name); }); test('the group the TLE came in is the last resort', () => { - assert.equal( - classify({ name: 'UNNAMED-1', group: 'resource', launchYear: 2024 }), - 'imaging', - ); - assert.equal( - classify({ name: 'UNNAMED-1', group: 'geo', launchYear: 2024 }), - 'telecom', - ); - assert.equal( - classify({ name: 'UNNAMED-1', group: 'science', launchYear: 2024 }), - 'probes', - ); + assert.equal(classify({ name: 'UNNAMED-1', group: 'resource', launchYear: 2024 }), 'imaging'); + assert.equal(classify({ name: 'UNNAMED-1', group: 'geo', launchYear: 2024 }), 'telecom'); + assert.equal(classify({ name: 'UNNAMED-1', group: 'science', launchYear: 2024 }), 'probes'); assert.equal(classify({ name: 'STARLINK-1', group: 'dense' }), 'starlink'); - assert.equal( - classify({ name: 'UNNAMED-1', group: 'visual', launchYear: 2024 }), - 'probes', - ); + assert.equal(classify({ name: 'UNNAMED-1', group: 'visual', launchYear: 2024 }), 'probes'); }); test('CubeSats deployed from the ISS are not stations', () => { // They ride in CelesTrak's stations group under the ISS's 1998 designator. - for (const name of [ - 'DUPLEX', - 'KNACKSAT-2', - 'GXIBA-1', - 'LEOPARD', - 'HMU-SAT2', - ]) { + for (const name of ['DUPLEX', 'KNACKSAT-2', 'GXIBA-1', 'LEOPARD', 'HMU-SAT2']) { assert.equal( classify({ name, group: 'stations', launchYear: 1998 }), 'probes', @@ -209,11 +161,7 @@ test('CubeSats deployed from the ISS are not stations', () => { ); } assert.equal( - classify({ - name: 'UNNAMED-1', - group: 'stations', - ucs: { purpose: 'Earth Observation' }, - }), + classify({ name: 'UNNAMED-1', group: 'stations', ucs: { purpose: 'Earth Observation' } }), 'imaging', ); }); @@ -226,53 +174,89 @@ test('an unknown old payload is presumed dead; a recognisable one is not', () => 'without a SATCAT record (a failed read) nothing is presumed', ); assert.equal( - classify({ - name: 'ATLAS CENTAUR 2', - group: 'visual', - launchYear: 1963, - satcat: { objectType: 'PAY', opsStatus: '' }, - }), + classify({ name: 'ATLAS CENTAUR 2', group: 'visual', launchYear: 1963, satcat: { objectType: 'PAY', opsStatus: '' } }), 'debris', 'a blank SATCAT status is no evidence of life', ); + assert.equal(classify({ name: 'UNNAMED-1', group: 'visual', launchYear: old + 1 }), 'probes'); + assert.equal(classify({ name: 'NOAA 15', group: 'weather', launchYear: 1998 }), 'imaging'); assert.equal( - classify({ name: 'UNNAMED-1', group: 'visual', launchYear: old + 1 }), - 'probes', - ); - assert.equal( - classify({ name: 'NOAA 15', group: 'weather', launchYear: 1998 }), - 'imaging', - ); - assert.equal( - classify({ - name: 'UNNAMED-1', - group: 'visual', - launchYear: 1990, - satcat: { objectType: 'PAY', opsStatus: '+' }, - }), + classify({ name: 'UNNAMED-1', group: 'visual', launchYear: 1990, satcat: { objectType: 'PAY', opsStatus: '+' } }), 'probes', 'SATCAT says it works', ); }); +test('only debris is refused the Cockpit', () => { + for (const id of SATELLITE_CLASS_IDS) + assert.equal(satelliteClassEnterable(id), id !== 'debris', id); + assert.equal(satelliteClassEnterable('nonsense'), false); +}); + test('class visibility merges booleans and ignores everything else', () => { - const next = mergeClassVisibility({ - telecom: true, - imaging: false, - debris: 'yes', - bogus: true, - }); - assert.deepEqual(next, { - ...DEFAULT_SATELLITE_CLASSES, - telecom: true, - imaging: false, - }); - assert.deepEqual(mergeClassVisibility(null), { - ...DEFAULT_SATELLITE_CLASSES, - }); + const next = mergeClassVisibility({ telecom: true, imaging: false, debris: 'yes', bogus: true }); + assert.deepEqual(next, { ...DEFAULT_SATELLITE_CLASSES, telecom: true, imaging: false }); + assert.deepEqual(mergeClassVisibility(null), { ...DEFAULT_SATELLITE_CLASSES }); assert.equal(Object.hasOwn(next, 'bogus'), false); }); +test('UCS owner countries normalise to ISO codes, organisations and joint owners', () => { + assert.deepEqual(ownerFromUcs('USA'), { countryCode: 'US', label: 'United States' }); + assert.deepEqual(ownerFromUcs('United Kingdom'), { countryCode: 'GB', label: 'United Kingdom' }); + assert.deepEqual(ownerFromUcs('Sinapore'), { countryCode: 'SG', label: 'Singapore' }, 'UCS typo'); + assert.deepEqual(ownerFromUcs('Turkey'), { countryCode: 'TR', label: 'Türkiye' }); + assert.deepEqual(ownerFromUcs('ESA'), { countryCode: null, label: 'ESA' }); + assert.deepEqual(ownerFromUcs('Multinational'), { countryCode: null, label: 'Multinational' }); + assert.deepEqual(ownerFromUcs('China/France'), { countryCode: null, label: 'China / France' }); + assert.deepEqual(ownerFromUcs('United Kingdom/ESA'), { countryCode: null, label: 'United Kingdom / ESA' }); + assert.equal(ownerFromUcs(''), null); + assert.equal(ownerFromUcs(null), null); +}); + +test('SATCAT owner codes normalise the same way', () => { + assert.deepEqual(ownerFromSatcat('US'), { countryCode: 'US', label: 'United States' }); + assert.deepEqual(ownerFromSatcat('PRC'), { countryCode: 'CN', label: 'China' }); + assert.deepEqual(ownerFromSatcat('CIS'), { countryCode: 'RU', label: 'Russia' }, 'former USSR'); + assert.deepEqual(ownerFromSatcat('ISRO'), { countryCode: 'IN', label: 'India' }); + assert.deepEqual(ownerFromSatcat('itso'), { countryCode: null, label: 'Intelsat' }); + assert.deepEqual(ownerFromSatcat('EUME'), { countryCode: null, label: 'EUMETSAT' }); + assert.deepEqual(ownerFromSatcat('PRES'), { countryCode: null, label: 'China / ESA' }); + assert.deepEqual(ownerFromSatcat('TMMC'), { countryCode: null, label: 'Turkmenistan / Monaco' }); + for (const code of ['TBD', 'UNK', '', null, 'ZZZZ']) assert.equal(ownerFromSatcat(code), null, String(code)); +}); + +test('owner prefers UCS, falls back to SATCAT, and Starlink is American', () => { + assert.deepEqual( + satelliteOwner({ ucs: { operatorCountry: 'ESA' }, satcat: { owner: 'FR' } }), + { countryCode: null, label: 'ESA' }, + ); + assert.deepEqual(satelliteOwner({ satcat: { owner: 'FR' } }), { countryCode: 'FR', label: 'France' }); + assert.deepEqual(satelliteOwner({ satelliteClass: 'starlink' }), { countryCode: 'US', label: 'United States' }); + assert.equal(satelliteOwner({}), null); + assert.equal(satelliteOperator({ ucs: { operator: 'Planet Labs, Inc.' } }), 'Planet Labs, Inc.'); + assert.equal(satelliteOperator({ satelliteClass: 'starlink' }), 'SpaceX'); + assert.equal(satelliteOperator({ satelliteClass: 'imaging' }), null); +}); + +const ISS_LINE1 = '1 25544U 98067A 24001.50000000 .00016717 00000-0 30370-3 0 9993'; +const ISS_LINE2 = '2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.50377579432323'; + +test('COSPAR ids come from TLE line 1, across the 1957 century pivot', () => { + assert.equal(cosparIdFromTleLine1(ISS_LINE1), '1998-067A'); + assert.equal(cosparIdFromTleLine1(ISS_LINE1.replace('98067A ', '24123BC ')), '2024-123BC'); + assert.equal(cosparIdFromTleLine1(ISS_LINE1.replace('98067A ', '57001A ')), '1957-001A'); + assert.equal(cosparIdFromTleLine1(ISS_LINE1.replace('98067A ', ' ')), null); + assert.equal(cosparIdFromTleLine1(null), null); +}); + +test('the TLE epoch is read as epoch milliseconds', () => { + const satrec = twoline2satrec(ISS_LINE1, ISS_LINE2); + // Day 001.5 of 2024: 1 January 2024, 12:00 UTC. + assert.ok(Math.abs(tleEpochMs(satrec) - Date.UTC(2024, 0, 1, 12)) < 1000); + assert.equal(tleEpochMs(null), null); + assert.equal(tleEpochMs({}), null); +}); + test('SATCAT CSV parses, quoted commas included, keyed by NORAD id', () => { const csv = [ 'OBJECT_NAME,OBJECT_ID,NORAD_CAT_ID,OBJECT_TYPE,OPS_STATUS_CODE,OWNER,LAUNCH_DATE', @@ -286,6 +270,8 @@ test('SATCAT CSV parses, quoted commas included, keyed by NORAD id', () => { assert.deepEqual(records.get(25544), { objectType: 'PAY', opsStatus: '+', + owner: 'ISS', + cosparId: '1998-067A', launchDate: '1998-11-20', }); assert.equal(records.get(733).objectType, 'R/B'); diff --git a/src/layers/satellites/ingestion.js b/src/layers/satellites/ingestion.js index ee9477fc6..5d1624de0 100644 --- a/src/layers/satellites/ingestion.js +++ b/src/layers/satellites/ingestion.js @@ -322,6 +322,8 @@ export function createIngestion({ groups, // satellite.js does not keep the designator the year match reads. launchYear, + line1: entry.line1, + line2: entry.line2, satelliteClass: classifySatellite({ noradId, name: entry.name, diff --git a/src/layers/satellites/state.js b/src/layers/satellites/state.js index 42823ee00..783cdcb4c 100644 --- a/src/layers/satellites/state.js +++ b/src/layers/satellites/state.js @@ -14,7 +14,7 @@ export function createState({ services }) { state._overlayHost = state.DEFAULT_OVERLAY_HOST; - // Satellite catalog: { noradId → { name, satrec, group, launchYear, + // Satellite catalog: { noradId → { name, satrec, group, line1, line2, // satelliteClass, ucs, satcat } } — class, UCS and SATCAT records from // src/layers/satellites/classes.js and the sources the update read. From 048293fc2a5923772660322bc1cf89571042558b Mon Sep 17 00:00:00 2001 From: Denis Groshev Date: Wed, 4 Nov 2026 20:06:33 +0100 Subject: [PATCH 02/12] feat(cockpit): ride a tracked satellite in an orbital view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With a satellite tracked and no aircraft tracked, Cockpit can ride the satellite. Entry needs only the Satellites layer; debris can be tracked but not entered, and voice stays aircraft-only. Double-clicking the tracked satellite or the entry buttons (reading ORBIT) enter it. The camera sits on the satellite's per-frame SGP4 position and looks straight down, turned to the ground track (north-up for a satellite with none). The optical zoom steps 1x to 8x with a focus pull, the arrows tilt the view up to 45 degrees off nadir, and Home or 0 returns to nadir. Off nadir the tilt reads its total angle first and the swath readout becomes an approximation marked with ≈. While in orbit the map leases flat Esri imagery, the cloud pass stays off and the view opens in the optical style. The orbital HUD names the satellite with its owner's flag (from the flag-icons package, loaded per country) or an organisation badge, its operator, class, NORAD and COSPAR ids and TLE epoch with the element lines on request, altitude, orbital speed and the sub-satellite point. CURRENTLY OVER names the country and its first-level division, or the sea, and from 8x the most prominent populated place nearby, looked up offline from the bundled Natural Earth packs (populated places are a new pack). The satellites layer hides the ridden satellite's own marks, dims the other orbit rings and ignores scene clicks and Escape while held. Exit restores the camera's field of view and the satellite's follow camera. C no longer enters or leaves Cockpit, bridge or orbit: it is left to the app-wide CCTV shortcut, and Escape or the exit button leave first person. --- DATA_SOURCES.md | 11 + README.md | 2 +- docs/CURRENT-STATE.md | 124 +- package-lock.json | 7 + package.json | 1 + scripts/build-admin-packs.mjs | 58 +- scripts/check-package-boundaries.mjs | 9 +- scripts/package-boundaries.json | 23 +- src/cameraHandoff.test.mjs | 2 +- src/cockpitCloudEffects.js | 17 +- src/cockpitCloudEffects.test.mjs | 8 + src/cockpitLook.js | 61 + src/cockpitLook.test.mjs | 58 + src/cockpitMarkup.test.mjs | 13 +- src/cockpitOrbital.js | 413 +++++++ src/cockpitOrbital.test.mjs | 302 +++++ src/contextModePolicy.js | 24 + src/contextModePolicy.test.mjs | 14 + src/data/local_data/natural_earth/README.md | 21 + .../natural_earth/populated_places.json | 1 + src/data/placeBelow.js | 369 ++++++ src/data/placeBelow.test.mjs | 280 +++++ src/i18n/locales/ar.json | 40 +- src/i18n/locales/de.json | 40 +- src/i18n/locales/es.json | 40 +- src/i18n/locales/fr.json | 40 +- src/i18n/locales/it.json | 40 +- src/i18n/locales/ja.json | 40 +- src/i18n/locales/pt.json | 40 +- src/i18n/locales/ru.json | 40 +- src/i18n/locales/uk.json | 40 +- src/i18n/locales/zh-CN.json | 40 +- src/i18n/locales/zh-Hant.json | 40 +- src/i18n/same-as-english.json | 49 +- src/layers/satellites/cockpitSubject.js | 318 +++++ src/layers/satellites/cockpitSubject.test.mjs | 542 ++++++++ src/layers/satellites/controls.js | 8 +- src/layers/satellites/index.js | 3 + src/layers/satellites/ingestion.js | 2 + src/layers/satellites/interaction.js | 5 + src/layers/satellites/lifecycle.js | 4 + src/layers/satellites/orbits.js | 64 +- src/layers/satellites/rendering.js | 23 +- src/layers/satellites/state.js | 11 + src/layers/satellites/tracking.js | 3 + src/ui/applicationShell.js | 10 + src/ui/cockpitBodyClasses.test.mjs | 5 +- src/ui/cockpitBridge.test.mjs | 84 +- src/ui/cockpitBriefing.js | 2 +- src/ui/cockpitCamera.js | 4 + src/ui/cockpitController.js | 84 +- src/ui/cockpitCoordinator.js | 48 +- src/ui/cockpitEntryGate.test.mjs | 110 +- src/ui/cockpitInput.js | 61 +- src/ui/cockpitInstruments.js | 5 + src/ui/cockpitOrbital.test.mjs | 263 ++++ src/ui/cockpitOrbitalView.js | 549 +++++++++ src/ui/cockpitOrbitalView.test.mjs | 1090 +++++++++++++++++ src/ui/cockpitPresentation.js | 18 +- src/ui/cockpitTrackingController.js | 105 +- src/ui/ownerFlag.js | 110 ++ src/ui/ownerFlag.test.mjs | 108 ++ src/ui/stores/cockpit.js | 38 + src/ui/styles/cockpitOrbital.css | 499 ++++++++ src/ui/views/CockpitView.vue | 51 +- src/ui/views/panels/CockpitOrbital.vue | 279 +++++ style.css | 1 + 67 files changed, 6642 insertions(+), 172 deletions(-) create mode 100644 src/cockpitOrbital.js create mode 100644 src/cockpitOrbital.test.mjs create mode 100644 src/data/local_data/natural_earth/populated_places.json create mode 100644 src/data/placeBelow.js create mode 100644 src/data/placeBelow.test.mjs create mode 100644 src/layers/satellites/cockpitSubject.js create mode 100644 src/layers/satellites/cockpitSubject.test.mjs create mode 100644 src/ui/cockpitOrbital.test.mjs create mode 100644 src/ui/cockpitOrbitalView.js create mode 100644 src/ui/cockpitOrbitalView.test.mjs create mode 100644 src/ui/ownerFlag.js create mode 100644 src/ui/ownerFlag.test.mjs create mode 100644 src/ui/styles/cockpitOrbital.css create mode 100644 src/ui/views/panels/CockpitOrbital.vue diff --git a/DATA_SOURCES.md b/DATA_SOURCES.md index 52f72641c..cde514841 100644 --- a/DATA_SOURCES.md +++ b/DATA_SOURCES.md @@ -233,6 +233,7 @@ The [Bhote Koshi event pack](public/events/bhote-koshi-2026/README.md), under `p | **Natural Earth physical regions** (1,046 land + 292 marine named polygons) | `natural_earth/` | **Public domain** | ✅ (no restrictions) | "Made with Natural Earth" (courtesy credit — not legally required) | | **DataSF Analysis Neighborhoods** (41 SF neighborhood polygons) | `neighborhoods/` | **PDDL 1.0** (public domain) | ✅ (no restrictions) | "City & County of San Francisco — DataSF" (courtesy — not legally required) | | **Natural Earth countries, states and provinces** (260 admin-0/map units + 4,587 admin-1 polygons) | `natural_earth/` | **Public domain** | ✅ (no restrictions) | "Made with Natural Earth" (courtesy credit — not legally required) | +| **Natural Earth populated places** (7,342 points: name, position, rank) | `natural_earth/` | **Public domain** | ✅ (no restrictions) | "Made with Natural Earth" (courtesy credit — not legally required) | | **US Census Bureau counties** (3,235 county polygons) | `us_census_counties/` | **Public domain** | ✅ (no restrictions) | "U.S. Census Bureau" (courtesy — not legally required) | | **US Census Bureau places** (32,629 city, town and CDP polygons) | `us_census_places/` | **Public domain** | ✅ (no restrictions) | "U.S. Census Bureau" (courtesy — not legally required) | | **Who's On First neighborhoods** (61,441 polygons) | `wof_neighborhoods/` | Per source: CC BY, ODC-By, Open Government licences, CC0, PDDL, public domain (folder `ATTRIBUTION.md`) | ✅ (attribution) | "Neighborhood boundaries: Who's On First and contributors"; per-source credits in the folder | @@ -317,6 +318,16 @@ https://www.naturalearthdata.com/about/terms-of-use/). We credit anyway: "Made w Earth". Registration in the in-app `dataCredits.js` attribution list ships with the resolver wiring (see below). +### Natural Earth populated places (`natural_earth/populated_places.json`) + +Natural Earth 10m populated places (`ne_10m_populated_places_simple`, the same pinned +`nvkelso/natural-earth-vector` commit and SHA-256 as the admin-1 build reads), reduced to one +row per place: name, latitude and longitude rounded to 3 decimals, `scalerank` and `rank_max` +(7,342 places, 229 KB). From 8x the orbital view names the most prominent place within half +its width ("Sichuan, China · near Chengdu"), offline, with the states and provinces pack giving +the division. Public domain; credited "Made with Natural Earth" with the other packs. Rebuild: +`node scripts/build-admin-packs.mjs --only places`; provenance in the folder README. + ### Sky background (`sky/`) Sources, licences, the changes CC BY asks to state, hashes and build commands diff --git a/README.md b/README.md index b957046ff..d4b53dc24 100644 --- a/README.md +++ b/README.md @@ -340,7 +340,7 @@ Choose a first-run mission, or try these in order. The GIFs show Google Photorea 7. **Talk to it** _(needs an OpenAI key)_: _"Take me to LAX and select the nearest airborne aircraft."_ 8. **Come home.** Hit **Reset Globe** — or just say _"zoom out to a globe view."_ -**Keyboard:** `1`–`6` visual styles · `H` HUD · `D` detection · `C` cockpit · `` ` `` frame rate · `Esc` out. Trackpad pinch zooms the globe. +**Keyboard:** `1`–`6` visual styles · `H` HUD · `D` detection · `C` CCTV · `` ` `` frame rate · `Esc` out. Trackpad pinch zooms the globe. --- diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index ab92553b2..653ba1d99 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -1530,14 +1530,13 @@ With no aircraft tracked, Cockpit can ride the selected AIS vessel instead. Entry needs only the layer of the vessel it rides, Live AIS Vessels, and a selected vessel; Contacts and every other layer may be off, before or during the bridge (`bridgeEntryAllowed` in `src/contextModePolicy.js`). A Context mode -change still in flight blocks entry until it settles. `C` enters it (when -the bridge cannot be entered, `C` stays the CCTV shortcut), and the -entry button reads BRIDGE with a ship icon both in Contacts (`#cockpit-entry`) -and under the selected vessel's Intel HUD readout in the bottom-right corner -(`#cockpit-entry-readout`, shown with the HUD on, in its Tactical and Cyber -layouts). Turning Live AIS Vessels off ends the bridge: the layer then has no -subject (`getCockpitSubject` returns null). The bridge picture uses AIS alone, -so no other feed being off makes it partial. +change still in flight blocks entry until it settles. Double-clicking the +selected vessel enters it, and the entry button reads BRIDGE with a ship icon +both in Contacts (`#cockpit-entry`) and under the selected vessel's Intel HUD +readout in the bottom-right corner (`#cockpit-entry-readout`, shown with the +HUD on, in its Tactical and Cyber layouts). Turning Live AIS Vessels off ends +the bridge: the layer then has no subject (`getCockpitSubject` returns null). +The bridge picture uses AIS alone, so no other feed being off makes it partial. Voice (`control_cockpit`) and the selection entry transaction stay aircraft-only; voice `enter` on a bridge is refused before it touches tracking, with the reason to exit the bridge first. @@ -1605,6 +1604,97 @@ through the layer's own focus. Tracking an aircraft or losing the vessel selection ends the bridge without refocusing the ship. `src/ui/cockpitBridge.test.mjs` covers entry, readouts, refusal and exit. +### Orbital view + +With a satellite tracked and no aircraft tracked, Cockpit can ride the +satellite instead. Entry needs only the Satellites layer +(`orbitEntryAllowed` in `src/contextModePolicy.js`); Contacts and every other +layer may be off. A Context mode change in flight blocks entry until it +settles. Debris (rocket bodies, fragments and dead satellites; see the +satellite class toggles) can be tracked but never entered: no ORBIT entry is +offered and double-click refuses it. A tracked aircraft still takes +entry first, and a tracked satellite +takes it before a selected vessel. Double-clicking the tracked satellite +enters it, and the entry button reads +ORBIT with a satellite icon in Contacts (`#cockpit-entry`) and under the Intel +HUD readout (`#cockpit-entry-readout`). Voice (`control_cockpit`) stays +aircraft-only; its state reports an orbital view in use as a `satellite` +subject. `gev:cockpit-mode-changed` carries layer `satellites` and the NORAD +id. + +The camera sits on the satellite's own per-frame SGP4 position +(`getCockpitPosition`, the sample the dot uses) and looks at the Earth's +centre track-up: the ground track points to the top of the frame, so the +picture scrolls along it (`nadirOrientation` in `src/cockpitOrbital.js`). A +satellite with no ground track (a geostationary one) is shown north-up, and +over a pole the previous frame's up is kept. It updates on every rendered +frame, with no ground clamp. Entry opens in the plain optical vision style +(the other styles stay one click away) and leases the map for flat imagery: +with Google 3D tiles shown, which stay coarse from hundreds of kilometres up, +the map switches to Esri imagery, and exit puts it back unless the operator +picked another map meanwhile; another owner already holding the map (an +imagery comparison) keeps it as it is. The Cockpit cloud pass is off in orbit +(it fades out above 24 km); cloud cover from orbit is the Weather layer's, +and the saved cloud preference stands for the next aircraft or bridge. The layer hides the satellite's dot, docked +companions, its own orbit ring and its detection bracket, and draws every +other orbit ring (the ISS ring included) at 30% of its alpha; other +satellites' points and labels stay. Scene clicks and the layer's Escape are +ignored while it is ridden. The optical zoom steps 1×, 2×, 4× and 8× with `+` +(or `=`) and `-` (or `_`) and the panel's buttons: the 1× frame is 60° +vertical in low orbit and fits the Earth's disk with margin from high orbits, +each step divides the tangent of the half-angle, and Cesium's `frustum.fov` +is set from it for the canvas aspect. A step animates over 400 ms with a +focus-pull blur and a reticle lock tick, and cuts at once under +`prefers-reduced-motion`. The arrows tilt the view off nadir in 5° steps +along the frame's axes (Up/Down tilt forward/aft along the ground track, +Left/Right across it, each axis to ±45°; Shift takes no larger step); Home, +`0` or NADIR return to nadir. While tilted the panel shows the total angle +from nadir, acos(cos along · cos across), before each axis +(`OFF-NADIR 18.0° · FWD 10° · RIGHT 15°`; N, S, E and W for a north-up view) +and a NADIR button, and the swath readout turns approximate +(`SWATH ≈ 26 KM`): an estimate of the ground width at the view's centre, the +nadir footprint scaled by 1/cos² of the tilt across the frame and 1/cos of +the tilt along it (`offNadirSwathScale`, flat Earth). At nadir it reads the +footprint without ≈. After a zoom step lands, the focus pull holds until the +imagery under the view has loaded (at most 2.5 s, `zoomSettleHolding`), then +the reticle locks. The look keys and zoom keys keep the bridge's focus +guards. + +The HUD (`#cockpit-hud[data-subject='satellite']`, body class +`cockpit-orbit`) mounts `CockpitOrbital` over the picture: name, class, +altitude, orbital speed, sub-satellite point, TRACK UP (NORTH UP without a +ground track) with a pointer that turns to keep north marked N on the frame, +zoom and swath. Under +the vision selector a "CURRENTLY OVER" band names what the sub-satellite point +is over, looked up offline from the bundled Natural Earth packs +(`src/data/placeBelow.js`: on land the first-level division as Natural Earth +names it and the country in the reader's language through `Intl.DisplayNames`, +"Sichuan, China", and from 8× the most prominent populated place within half +the view's smaller side, so it is in the picture, "Sichuan, China · near +Chengdu", from a bundled pack of Natural Earth populated places loaded on +first use; else the smallest named sea, gulf, strait, channel, sound or bay; +else the ocean; nothing in a coastline gap), at most every 2 s and only after +20 km of ground travel, or at once when a zoom step changes how much ground +the view shows. A division or populated-places pack that fails to load drops +only that part (the country still shows); a lookup that fails outright hides +the band rather than leave the last place up, and the next HUD beat looks +again. The readout card puts +the owner country's flag (an SVG from `flag-icons`, fetched only for the shown +country) or a text badge for an organisation before the name, the operator +under it, and a NORAD · COSPAR · TLE-epoch line whose TLE button unfolds the +two element lines; each row is left out when the satellites layer does not +know it. The +aircraft and bridge instruments, tapes, compass, radar, look controls, +position readout, route card and Contact card are hidden; the vision-style +switcher, briefing card (Local and Regional for the sub-satellite point; the +regional brief refreshes at most once a minute) and the reset and EXIT ORBIT +buttons stay, square-cornered like the bridge. Exit (`Escape`, EXIT +ORBIT) restores the camera's own field of view exactly and returns to the +satellite's follow camera through the layer's `refocusTrackedById`. Losing +the subject (tracking stopped, Satellites off) or tracking another target +ends the view without refocusing. `src/ui/cockpitOrbitalView.test.mjs` +covers entry, camera, zoom, look, HUD and exit. + ## Context coordination Context controls own Contacts/Space Missions state, entry and exit transactions, @@ -3495,7 +3585,7 @@ down | auth-failed` (plus the unchanged `missing-key`/`unsupported`) with > It uses the `radar` symbol; both tabs are reachable with Tab and Left/Right arrows switch between them. Its action row > places the single Cockpit entry before Search Nearby Sites. Cockpit removes > the duplicate floating map entry and topline exit; the bottom-center -> `EXIT COCKPIT` control (offset downward by a `-95px` bottom margin) plus `Escape`/`C` own exit, with entry/exit focus +> `EXIT COCKPIT` control (offset downward by a `-95px` bottom margin) plus `Escape` own exit, with entry/exit focus > transfer and failure-safe shortcut routing. The exit control sits at the > bottom-center compass position. A Cockpit-only control strip sits > directly above Live Signals, anchored 12px under the REC readout it shares @@ -5458,7 +5548,8 @@ silently demoting every later lookup for the session. - **Satellite classes** (`src/layers/satellites/classes.js`): every satellite is filed under one of six classes, each with its own point colour, legend swatch and toggle: STATIONS (warm white), IMAGING (cyan), TELECOM (violet; communications and navigation, so GPS, GLONASS, Galileo and BeiDou read as one family), STARLINK (dim slate), PROBES (muted blue-gray) and DEBRIS (receding brown-gray). That module is the single source of truth for class, label and colour, so the dot, the card and the legend swatch cannot disagree. Two deliberate palette rules: no class may sit in the 40–48° amber band, which is the app-wide known-military convention; and STARLINK stays far below PROBES in Rec.601 luminance so the dense shell stays separable when NVG/FLIR collapse the scene to one channel. The ISS keeps its long-standing red hero dot rather than the STATIONS colour — it carries a permanent name label and its card still reads `STATIONS · ISS`; it is a station whichever group ingested it, so a stations-feed outage cannot refile it. `src/data/satelliteClass.js` keeps the group-based labels beneath the classes: the constellation subtype and a group's own label for a satellite with no class. - Class is also a **text field**, not just a color: `TELECOM · GPS` / `STARLINK` / `STATIONS · ISS` leads the tracked card's detail block and replaces the raw CelesTrak tag on the detection-overlay label. Because that canvas composites above the post-FX chain, the class stays readable in NVG/FLIR after the in-scene dot colors are flattened. - The satellites row in DATA LAYERS carries per-layer sub-controls (`DataLayerManager._syncRowControls`, the first consumer of the optional `getRowControls()` layer hook): one chip per class (the STARLINK chip exposes the existing `catalog` param), a swatch legend with live per-class counts, and an info line while SATCAT is stale or unavailable (`Classes may lag: SATCAT is a cached copy` / `Classes may lag: SATCAT unavailable`). Default is the sparse core catalog. The chips are stateless — each declares the params to apply and the manager owns the write — so the Space Missions capture/restore path over the same param stays authoritative. Controls stay hidden while the layer is off. An explicit CORE or DENSE choice participates in versioned local and share-link state; temporary Space Missions overrides do not. -- **Class toggles** (`src/layers/satellites/classes.js`): the layer row carries one chip per class — STATIONS, IMAGING, TELECOM (communications and navigation), PROBES (science, technology development and demonstration, unknown purpose) and DEBRIS (rocket bodies, fragments, unknown objects launched before last year and dead payloads) on by default, so the layer shows what it did before classes; STARLINK off, as DENSE was. Points of a hidden class stay built and are only hidden, so a toggle needs no reload; hidden classes are left out of the detection overlay, the voice/framing position lists and analyst answers (the tracked satellite still answers), and the legend keys only the classes on screen. The class comes, strongest evidence first, from CelesTrak SATCAT (object type and operational status, fetched per group through `/api/celestrak-satcat/`, cached a day by the proxy; the layer keeps a current read six hours rather than asking on every five-minute update), the bundled UCS Satellite Database pack (UCS-Satellite-Database 5-1-2023: operator, owner country and purpose; `src/data/local_data/ucs_satellites/`), name patterns for satellites launched after May 2023, and finally the CelesTrak groups the TLE came in (a mission group such as `weather` before the orbit group `geo`; a UCS purpose of "Unknown" counts as none). Only crewed stations and the craft that visit them, by name, are STATIONS: the CubeSats CelesTrak's stations group also carries after their deployment from the ISS are classed like any other satellite. A payload whose SATCAT record gives no status, with no UCS record and no recognisable name, that launched 20 or more years ago (SATCAT's launch date, else the TLE designator's year) is presumed dead and filed as debris; without a SATCAT record (a failed read) nothing is presumed. To cover imaging launched after the UCS snapshot the core catalog also reads CelesTrak's `resource`, `weather`, `planet`, `sar` and `science` groups. Retired stations and the shuttles have re-entered and have no orbit to show. An explicit class choice is kept in local and share-link state as the `classes` option, one letter per class shown (`sitpd`: stations, imaging, telecom, probes, debris; `0`: none; `src/data/satelliteClassMask.js`), and the layer takes those letters back through `setParams({classes})`; STARLINK maps to the existing `catalog: 'dense'` param instead. +- **Class toggles** (`src/layers/satellites/classes.js`): the layer row carries one chip per class — STATIONS, IMAGING, TELECOM (communications and navigation), PROBES (science, technology development and demonstration, unknown purpose) and DEBRIS (rocket bodies, fragments, unknown objects launched before last year and dead payloads) on by default, so the layer shows what it did before classes; STARLINK off, as DENSE was. Points of a hidden class stay built and are only hidden, so a toggle needs no reload; hidden classes are left out of the detection overlay, the voice/framing position lists and analyst answers (the tracked satellite still answers), and the legend keys only the classes on screen. The class comes, strongest evidence first, from CelesTrak SATCAT (object type and operational status, fetched per group through `/api/celestrak-satcat/`, cached a day by the proxy; the layer keeps a current read six hours rather than asking on every five-minute update), the bundled UCS Satellite Database pack (UCS-Satellite-Database 5-1-2023: operator, owner country and purpose; `src/data/local_data/ucs_satellites/`), name patterns for satellites launched after May 2023, and finally the CelesTrak groups the TLE came in (a mission group such as `weather` before the orbit group `geo`; a UCS purpose of "Unknown" counts as none). Only crewed stations and the craft that visit them, by name, are STATIONS: the CubeSats CelesTrak's stations group also carries after their deployment from the ISS are classed like any other satellite. A payload whose SATCAT record gives no status, with no UCS record and no recognisable name, that launched 20 or more years ago (SATCAT's launch date, else the TLE designator's year) is presumed dead and filed as debris; without a SATCAT record (a failed read) nothing is presumed. To cover imaging launched after the UCS snapshot the core catalog also reads CelesTrak's `resource`, `weather`, `planet`, `sar` and `science` groups. Debris can be tracked but is never ridden: the orbital entry gate (`orbitEntryAllowed`) refuses it, so no ORBIT entry is offered and double-click does nothing for it. Retired stations and the shuttles have re-entered and have no orbit to show. An explicit class choice is kept in local and share-link state as the `classes` option, one letter per class shown (`sitpd`: stations, imaging, telecom, probes, debris; `0`: none; `src/data/satelliteClassMask.js`), and the layer takes those letters back through `setParams({classes})`; STARLINK maps to the existing `catalog: 'dense'` param instead. +- The satellite Cockpit subject (`getCockpitSubject()`) also carries `satelliteClass`, `cosparId` (from SATCAT, else TLE line 1), `tle` (`{line1, line2, epochMs}`), `owner` (`{countryCode, label}`: ISO 3166-1 alpha-2 for a single country, `null` code for organisations such as ESA, EUMETSAT or Intelsat and for joint owners) and `operator` (UCS; SpaceX for Starlink). UCS names the operator's country and wins over the SATCAT owner code; CelesTrak's CIS (former USSR) is filed under Russia. - **The STARLINK chip (formerly DENSE) reports the dense LOAD, not the catalog param.** The param flips synchronously while the Starlink shell takes seconds to arrive over a chunked load, and CelesTrak 502s that feed regularly. So the chip reads `STARLINK ···` (busy, disabled) while loading, ACTIVE only once dense points are actually on screen, and `STARLINK ✕` with the reason on hover when the load fails — a failure also reverts `catalog` to `core`, drops any partial chunk, and leaves the chip clickable to retry. A load is judged by points added, not by HTTP status: a 200 carrying an empty body, a passed-through HTML error page, or only TLEs the core catalog already owns fails with the same revert semantics as a 502. Any explicit request for `core` clears a latched error even when the mode does not change, so a Space Missions restore of an already-core snapshot never leaves the user with a failure they did not cause. Because the load settles asynchronously, the layer pushes a re-render through the optional `setRowControlsListener()` hook; nothing else would repaint that row before the 5-minute catalog refresh, so the count and legend would otherwise sit stale. - **A dependency owner takes the row with it.** Space Missions borrows this layer for TLE lookup with `showPoints:false`; while points are hidden the layer returns empty row controls, so the legend never describes an empty sky and the chip cannot accept a write that the owner's restore would silently revert. - The detection-overlay record cache (`_detectionObjects`) is cleared with the catalog on every rebuild: it stamps id/class at creation only, and a rebuild can re-tag a satellite when a partial CelesTrak outage changes which group wins dedupe. @@ -6358,15 +6449,16 @@ apply to `public/` assets or built-preview serving. ending, by its own switch or one of its layers going off, restores the pre-Contacts layers but keeps the ridden one and the view; Live Signals then drops the rows Contacts built and shows `CONTEXT STANDBY`. The visible - Cockpit actions, the `C` shortcut and voice use the same gate; voice entry - still opens Contacts first, as its layer-targeted entry navigates through - Contacts. The ship bridge has its own own-layer gate (`bridgeEntryAllowed`; - see [Ship bridge view](#ship-bridge-view)). -- **Aircraft cockpit view:** selecting a commercial or military aircraft reveals a `COCKPIT` action (`C`) once that aircraft's own layer is on; Contacts is not required. The action shows in Contacts (`#cockpit-entry`) and under the Intel HUD's bottom-right readout (`#cockpit-entry-readout`, with the HUD on, in its Tactical and Cyber layouts), so entry needs no Contacts panel. Turning off the ridden aircraft's layer ends the view (the layer clears its tracking). When an air feed the surrounding picture uses is off, the Cockpit says so instead of blocking: Live Signals leads with `MILITARY FEED OFF · PARTIAL PICTURE` or `FLIGHTS FEED OFF · PARTIAL PICTURE`, and the Contact card shows that line in place of its inputs status, so a partial picture is never presented as complete. `control_cockpit` refuses entry with `entryBlockedReason` `contacts-starting` (a Context change in flight), `subject-layer-off` (the aircraft's layer, or with none tracked any aircraft layer, is off) or `no-tracked-aircraft`. Cockpit mode temporarily releases Cesium's orbit-follow transform and drives a first-person camera from the tracked aircraft's existing smoothed display position and course. Its concave helmet-visor HUD shows callsign, UTC time, coordinates, curved roll/pitch guides, and a seven-division heading tape. Ambient commercial and military AIR contacts use a Cockpit near/far band selected by the shared Display 3D mode: Proximity admits at 150 km and retains to 185 km; All admits at 400 km and retains to 450 km. The shared 3D toggle now applies in Cockpit: Off keeps in-range contacts as rotating 2D aircraft silhouettes, while On lets a ready admitted glTF take over without a drawing gap. The Cockpit model cap remains 60 and can only lower the map budget; in-range contacts that are capped or still loading remain 2D silhouettes instead of degrading to out-of-range dots. Contacts outside the selected band use small rotation-free cyan-white pips for civilian aircraft and amber pips for military. The pilot's own airframe is not drawn in first person, and exiting clears the Cockpit band and restores normal map silhouettes/models. The normal left accordion remains available for Layers and Authoring and keeps the same 26vh HUD-aligned anchor used in map mode, independent of whether the bottom-left Contact card is expanded or collapsed; the right-rail CCTV and Context chooser are hidden to avoid duplicating or overlapping the cockpit presentation. When the intelligence HUD is enabled, its classification, scene summary, collection/orbit metadata, coordinates, and imaging-status text remain visible as reduced peripheral cockpit telemetry; the optical center and flight instruments stay clear, and turning the HUD off still hides it. Ground speed, exact heading, and rendered altitude form one compact lower-center instrument cluster, keeping the horizon and peripheral view open. A second live altitude tape hugs the inside-right visor rim: its rail and nine moving ticks are derived from the same responsive keyhole radius, remain 20 px inside the circular edge even on wide displays, fade deeply at both vertical ends, and move continuously behind a fixed current-altitude pointer; its interval tightens automatically near the surface and it is suppressed on narrow screens. Cockpit mode also has a weather-backed transparent volumetric-cloud pass derived from the supplied FBM/domain-warped R&D shader. It renders at no more than 520×320, uses 24 ray steps/three FBM octaves at 12 FPS, is clipped to the visor, fails clear when Open-Meteo is unavailable, and stops its animation completely on cockpit exit. It does not restore the prior CPU weather canvases, precipitation, scene fog, or any map-mode effect. When Contacts is active for the tracked aircraft, the compact `CONTACT` rail adds the 250 km subject window, four cohort counts, nearest observed/mapped example with relative bearing and distance, freshness, explicit uncertainty, and Previous and Next controls plus its own collapse control. The mirrored right rail is a three-page **cockpit briefing carousel**: source-backed live signals, location-matched regional headlines, and physical-region/current-weather context from bundled Natural Earth polygons and Open-Meteo. It is manual-first: Previous, Next, and direct page controls are always available, and the visible `CYCLE OFF` / `CYCLE ON` control starts or stops the nine-second page cycle. The cycle pauses on hover or keyboard focus and stops while collapsed, hidden, or outside cockpit mode; live signal data continues refreshing either way. Empty news matches and unavailable news use compact text states rather than reserving an empty media frame; partial local data remains explicit. Article links open their original publisher, and no headline is treated as verified risk intelligence. On desktop both cockpit rails use the same width and share a bottom-aligned safe baseline in opposite corners above the peripheral MGRS/GSD/time telemetry, leaving both that text and the lower-center instrument cluster readable. They collapse independently to slim tabs without stopping live data updates. Narrow screens use separated top/bottom fallbacks. Empty-space globe clicks are inert while cockpit owns the camera; `C`, `Escape`, or `EXIT COCKPIT` explicitly exits and restores the same tracked entity and standard follow camera. Unknown feeds remain unknown, selection loss still exits safely without inventing a replacement track, and the cockpit never presents the summary as threat scoring or an all-clear. This is a desktop first-person presentation, not a WebXR session. + Cockpit actions, double-click and voice use the same gate; voice entry still + opens Contacts first, as its layer-targeted entry navigates through Contacts. + The ship bridge and the orbital view have their own own-layer gates + (`bridgeEntryAllowed`, `orbitEntryAllowed`; see + [Ship bridge view](#ship-bridge-view) and [Orbital view](#orbital-view)). +- **Aircraft cockpit view:** selecting a commercial or military aircraft reveals a `COCKPIT` action once that aircraft's own layer is on; Contacts is not required. The action shows in Contacts (`#cockpit-entry`) and under the Intel HUD's bottom-right readout (`#cockpit-entry-readout`, with the HUD on, in its Tactical and Cyber layouts), so entry needs no Contacts panel. Turning off the ridden aircraft's layer ends the view (the layer clears its tracking). When an air feed the surrounding picture uses is off, the Cockpit says so instead of blocking: Live Signals leads with `MILITARY FEED OFF · PARTIAL PICTURE` or `FLIGHTS FEED OFF · PARTIAL PICTURE`, and the Contact card shows that line in place of its inputs status, so a partial picture is never presented as complete. `control_cockpit` refuses entry with `entryBlockedReason` `contacts-starting` (a Context change in flight), `subject-layer-off` (the aircraft's layer, or with none tracked any aircraft layer, is off) or `no-tracked-aircraft`. Cockpit mode temporarily releases Cesium's orbit-follow transform and drives a first-person camera from the tracked aircraft's existing smoothed display position and course. Its concave helmet-visor HUD shows callsign, UTC time, coordinates, curved roll/pitch guides, and a seven-division heading tape. Ambient commercial and military AIR contacts use a Cockpit near/far band selected by the shared Display 3D mode: Proximity admits at 150 km and retains to 185 km; All admits at 400 km and retains to 450 km. The shared 3D toggle now applies in Cockpit: Off keeps in-range contacts as rotating 2D aircraft silhouettes, while On lets a ready admitted glTF take over without a drawing gap. The Cockpit model cap remains 60 and can only lower the map budget; in-range contacts that are capped or still loading remain 2D silhouettes instead of degrading to out-of-range dots. Contacts outside the selected band use small rotation-free cyan-white pips for civilian aircraft and amber pips for military. The pilot's own airframe is not drawn in first person, and exiting clears the Cockpit band and restores normal map silhouettes/models. The normal left accordion remains available for Layers and Authoring and keeps the same 26vh HUD-aligned anchor used in map mode, independent of whether the bottom-left Contact card is expanded or collapsed; the right-rail CCTV and Context chooser are hidden to avoid duplicating or overlapping the cockpit presentation. When the intelligence HUD is enabled, its classification, scene summary, collection/orbit metadata, coordinates, and imaging-status text remain visible as reduced peripheral cockpit telemetry; the optical center and flight instruments stay clear, and turning the HUD off still hides it. Ground speed, exact heading, and rendered altitude form one compact lower-center instrument cluster, keeping the horizon and peripheral view open. A second live altitude tape hugs the inside-right visor rim: its rail and nine moving ticks are derived from the same responsive keyhole radius, remain 20 px inside the circular edge even on wide displays, fade deeply at both vertical ends, and move continuously behind a fixed current-altitude pointer; its interval tightens automatically near the surface and it is suppressed on narrow screens. Cockpit mode also has a weather-backed transparent volumetric-cloud pass derived from the supplied FBM/domain-warped R&D shader. It renders at no more than 520×320, uses 24 ray steps/three FBM octaves at 12 FPS, is clipped to the visor, fails clear when Open-Meteo is unavailable, and stops its animation completely on cockpit exit. It does not restore the prior CPU weather canvases, precipitation, scene fog, or any map-mode effect. When Contacts is active for the tracked aircraft, the compact `CONTACT` rail adds the 250 km subject window, four cohort counts, nearest observed/mapped example with relative bearing and distance, freshness, explicit uncertainty, and Previous and Next controls plus its own collapse control. The mirrored right rail is a three-page **cockpit briefing carousel**: source-backed live signals, location-matched regional headlines, and physical-region/current-weather context from bundled Natural Earth polygons and Open-Meteo. It is manual-first: Previous, Next, and direct page controls are always available, and the visible `CYCLE OFF` / `CYCLE ON` control starts or stops the nine-second page cycle. The cycle pauses on hover or keyboard focus and stops while collapsed, hidden, or outside cockpit mode; live signal data continues refreshing either way. Empty news matches and unavailable news use compact text states rather than reserving an empty media frame; partial local data remains explicit. Article links open their original publisher, and no headline is treated as verified risk intelligence. On desktop both cockpit rails use the same width and share a bottom-aligned safe baseline in opposite corners above the peripheral MGRS/GSD/time telemetry, leaving both that text and the lower-center instrument cluster readable. They collapse independently to slim tabs without stopping live data updates. Narrow screens use separated top/bottom fallbacks. Empty-space globe clicks are inert while cockpit owns the camera; `Escape` or `EXIT COCKPIT` explicitly exits and restores the same tracked entity and standard follow camera. Unknown feeds remain unknown, selection loss still exits safely without inventing a replacement track, and the cockpit never presents the summary as threat scoring or an all-clear. This is a desktop first-person presentation, not a WebXR session. - **Cockpit left-panel clearance:** the Cockpit Contact card and peripheral HUD participate in the adaptive left accordion's live obstacle measurements, including live viewport-height changes. Expanding Layers or Authoring keeps the active panel in the available upper-left corridor with internal scrolling; it does not cover the Contact card, lower Cockpit controls, or Cesium credit line. Outside Cockpit the hidden card does not alter the normal corridor. - **Cockpit Context scope:** the 250 km radius applies to the air/sea proximity cohorts. Installation counts come only from the currently loaded viewport and are labeled `CURRENT VIEWPORT ONLY` in the cockpit as well as the normal Context panel; neither surface presents them as a complete 250 km installation survey. - **Cockpit camera anchor:** first-person mode does not write feed-boundary corrections directly into the camera. A cockpit-only inertial anchor advances from the selected aircraft's displayed course and speed, then converges toward the authoritative delayed track with correction capped below forward motion. The displayed kinematics are derived from the same consecutive fix segment as the rendered position, with raw feed speed/course used only as fallback; a transient zero/missing feed speed therefore cannot freeze a visibly moving aircraft after layer enable or a map/cockpit handoff. Rendered altitude continues to come from that interpolated track position. Late ADS-B fixes and short render stalls can remove drift without accelerating or reversing the view. Camera placement runs before scene update/culling at a bounded 20 Hz so a moving cockpit does not force Photoreal 3D Tiles to retraverse on every display frame; textual instruments update at 10 Hz and context/layout work at 4 Hz. Every far Cockpit contact pip shares one stable Cesium texture-atlas entry and skips unused screen-projected course calculations, while only in-range 2D aircraft silhouettes pay the screen-projected rotation cost; ambient glTF collections are hidden/retained rather than synchronously destroyed at cockpit entry, and context rails lay out only on explicit content/state changes and viewport resize. The deliberate 15/30-second layer interpolation delays and per-Cesium-frame position caches remain unchanged. -- **Cockpit route, vision, and view controls:** visible on-screen `COCKPIT`, `RESET`, and `EXIT COCKPIT` controls replace reliance on the `C` shortcut. RESET uses the same canonical globe route as the map and voice actions, exits Cockpit, and releases its camera ownership rather than exposing the hidden map-style top action. When the tracked commercial flight has a plausible ADSBDB route, the top of the right briefing rail shows a compact `FROM → TO` airport strip and the visor shows a centered estimated-destination chevron with its relative bearing; its destination label rounds to whole degrees in 000–359, wrapping rounded north to 000° while the chevron continues to use the relative bearing independently of label rounding; absent or implausible route data hides the strip and cue rather than guessing. The cockpit-local vision control is an interactive `PREV / CURRENT / NEXT` carousel over `NORMAL`, `CRT`, `NVG`, `FLIR`, `ANIME`, and `NOIR`; its previous/next actions wrap, and activating the current value advances to the next style. Cockpit enters on the active map preset, so a Cyber FLIR map opens Cockpit on FLIR while Normal remains a distinct option instead of producing a second FLIR entry. Cockpit choices temporarily activate the existing Cesium post-process stages, while exiting Cockpit through either EXIT or RESET restores the pre-entry map style. The regional-news page uses a free Google News RSS locality query first, with the existing GDELT query retained only as a fail-soft fallback; linked headlines remain reporting, not verified incidents or risk intelligence. +- **Cockpit route, vision, and view controls:** visible on-screen `COCKPIT`, `RESET`, and `EXIT COCKPIT` controls are the way in and out; Cockpit claims no `C` shortcut, so `C` keeps toggling CCTV, also inside a first-person view. RESET uses the same canonical globe route as the map and voice actions, exits Cockpit, and releases its camera ownership rather than exposing the hidden map-style top action. When the tracked commercial flight has a plausible ADSBDB route, the top of the right briefing rail shows a compact `FROM → TO` airport strip and the visor shows a centered estimated-destination chevron with its relative bearing; its destination label rounds to whole degrees in 000–359, wrapping rounded north to 000° while the chevron continues to use the relative bearing independently of label rounding; absent or implausible route data hides the strip and cue rather than guessing. The cockpit-local vision control is an interactive `PREV / CURRENT / NEXT` carousel over `NORMAL`, `CRT`, `NVG`, `FLIR`, `ANIME`, and `NOIR`; its previous/next actions wrap, and activating the current value advances to the next style. Cockpit enters on the active map preset, so a Cyber FLIR map opens Cockpit on FLIR while Normal remains a distinct option instead of producing a second FLIR entry. Cockpit choices temporarily activate the existing Cesium post-process stages, while exiting Cockpit through either EXIT or RESET restores the pre-entry map style. The regional-news page uses a free Google News RSS locality query first, with the existing GDELT query retained only as a fail-soft fallback; linked headlines remain reporting, not verified incidents or risk intelligence. - Cockpit wind-direction labels wrap after rounding to whole degrees, so a direction of 359.5° displays as `N · 0°` rather than `N · 360°`. - The transit, ALPR, vessel, CCTV, Local ADS-B, flight and military context, awareness, Cockpit and Street Level heading readouts round through `roundHeadingDegrees` in `src/data/headingDegrees.js` (whole degrees 0–359, `null` when not finite, so each caller keeps its own placeholder); `normalizeHeading` lives there too and `cockpitMath.js` re-exports it. The Cockpit's `TRACK ACQUIRED` signal uses `formatHeadingReadout`, so a 359.6° track reads `COURSE 000°`. - **Cockpit missing observations:** missing local weather observations remain unknown rather than being converted to zero or clear skies, in the briefing and in the cloud effects; a missing temperature drops the whole local weather record, including its wind and condition. diff --git a/package-lock.json b/package-lock.json index dd60d3383..87c2cb80b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@meri-imperiumi/eccodes-wasm": "^2.48.2", "cesium": "^1.124.0", "egm96-universal": "^1.1.1", + "flag-icons": "7.5.0", "hls.js": "^1.7.3", "mapillary-js": "^4.1.2", "mgrs": "^2.1.0", @@ -2411,6 +2412,12 @@ } } }, + "node_modules/flag-icons": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-7.5.0.tgz", + "integrity": "sha512-kd+MNXviFIg5hijH766tt+3x76ele1AXlo4zDdCxIvqWZhKt4T83bOtxUOOMlTx/EcFdUMH5yvQgYlFh1EqqFg==", + "license": "MIT" + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", diff --git a/package.json b/package.json index ffc554d7b..f6362281f 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@meri-imperiumi/eccodes-wasm": "^2.48.2", "cesium": "^1.124.0", "egm96-universal": "^1.1.1", + "flag-icons": "7.5.0", "hls.js": "^1.7.3", "mapillary-js": "^4.1.2", "mgrs": "^2.1.0", diff --git a/scripts/build-admin-packs.mjs b/scripts/build-admin-packs.mjs index d7f647384..9fe319ee0 100644 --- a/scripts/build-admin-packs.mjs +++ b/scripts/build-admin-packs.mjs @@ -7,13 +7,16 @@ * Natural Earth 10m admin-1 states and provinces (public domain). * src/data/local_data/us_census_counties/counties.json * US Census Bureau cartographic boundary counties (public domain). + * src/data/local_data/natural_earth/populated_places.json + * Natural Earth 10m populated places as points, for the orbital view's + * "near " (`src/data/placeBelow.js`; public domain). * * Both sources are pinned by URL and SHA-256, so a rerun reproduces the packs * byte for byte. Downloads are cached outside the repository (default: the * system temp directory) and are never committed. * * Usage: - * node scripts/build-admin-packs.mjs [--cache ] [--only countries|admin1|counties] + * node scripts/build-admin-packs.mjs [--cache ] [--only countries|admin1|counties|places] * * The provenance READMEs beside each pack record these parameters. */ @@ -101,6 +104,9 @@ export const PARAMS = Object.freeze({ elsewhereMinPopulation: 50_000, cityStateMaxKm2: 1_000, }, + // Every populated place, kept as a point: name, position and the two + // prominence ranks the orbital view picks "near " by. + places: { decimals: 3 }, }); const args = process.argv.slice(2); @@ -688,6 +694,47 @@ async function buildAdmin1() { }; } +async function buildPlaces() { + const params = PARAMS.places; + const source = await fetchPinned('places'); + const factor = 10 ** params.decimals; + const round = (value) => Math.round(value * factor) / factor; + const places = JSON.parse(source.bytes.toString('utf8')) + .features.map((f) => f.properties) + .filter( + (p) => + p.name && + Number.isFinite(p.latitude) && + Number.isFinite(p.longitude) && + Number.isFinite(p.scalerank), + ) + .map((p) => [ + p.name, + round(p.latitude), + round(p.longitude), + p.scalerank, + Number.isFinite(p.rank_max) ? p.rank_max : 0, + ]) + .sort((a, b) => a[3] - b[3] || b[4] - a[4] || a[0].localeCompare(b[0])); + return { + meta: { + title: 'Natural Earth populated places', + source: 'ne_10m_populated_places_simple', + url: SOURCES.places.url, + sha256: source.digest, + commit: NE_COMMIT, + license: + 'Public domain (https://www.naturalearthdata.com/about/terms-of-use/)', + schema: + 'places[]: [name, latitude, longitude, scalerank (0 most prominent .. 10), rank_max (population class, 0..14; higher is larger)]', + decimals: params.decimals, + curation: params, + script: 'scripts/build-admin-packs.mjs', + }, + places, + }; +} + async function buildCounties() { const params = PARAMS.counties; const source = await fetchPinned('counties'); @@ -768,4 +815,13 @@ if (isMain) { 'src/data/local_data/us_census_counties/counties.json', await buildCounties(), ); + if (!only || only === 'places') { + const relative = 'src/data/local_data/natural_earth/populated_places.json'; + const pack = await buildPlaces(); + const text = JSON.stringify(pack) + '\n'; + await writeFile(path.join(ROOT, relative), text); + console.log( + `${relative}: ${pack.places.length} places, ${Buffer.byteLength(text)} bytes`, + ); + } } diff --git a/scripts/check-package-boundaries.mjs b/scripts/check-package-boundaries.mjs index 700dc9a1a..ad5d2bdb2 100644 --- a/scripts/check-package-boundaries.mjs +++ b/scripts/check-package-boundaries.mjs @@ -109,7 +109,14 @@ export async function checkPackageBoundaries(root) { // template blocks belong to the component file itself. if (info.id.startsWith('\0')) return; const id = info.id.split('?')[0]; - if (!allowed.has(id)) { + // A declared dependency also owns the asset files it ships (a + // flag-icons SVG imported as a URL) that a glob resolves in place. + const dependencyAsset = group.external.some((external) => + id.startsWith( + `${normalizePath(path.join(root, 'node_modules', external))}/`, + ), + ); + if (!allowed.has(id) && !dependencyAsset) { throw new Error( `Package boundary ${name} imports an unowned module: ${path.relative(root, id)}`, ); diff --git a/scripts/package-boundaries.json b/scripts/package-boundaries.json index f5443b2e5..466606b92 100644 --- a/scripts/package-boundaries.json +++ b/scripts/package-boundaries.json @@ -40,6 +40,8 @@ "src/ui/views/panels/CockpitContext.vue", "src/ui/views/panels/CockpitRoute.vue", "src/ui/views/panels/CockpitRadar.vue", + "src/ui/views/panels/CockpitOrbital.vue", + "src/ui/ownerFlag.js", "src/ui/cockpitPresentation.js", "src/data/headingDegrees.js", "src/data/distanceFormat.js", @@ -158,7 +160,7 @@ "src/ui/i18n.js", "src/ui/surfaceKeyboard.js" ], - "external": ["vue", "pinia", "vue-i18n"] + "external": ["vue", "pinia", "vue-i18n", "flag-icons"] }, "viewer": { "exports": ["./application/viewer"], @@ -891,6 +893,11 @@ "src/ui/cockpitInstrumentState.js", "src/ui/cockpitRollingValue.js", "src/ui/cockpitCamera.js", + "src/ui/cockpitOrbitalView.js", + "src/data/placeBelow.js", + "src/data/adminBoundaries.js", + "src/data/bundledJson.js", + "src/data/retryableLoad.js", "src/ui/cockpitContext.js", "src/ui/cockpitController.js", "src/ui/cockpitDisplayPortal.js", @@ -908,6 +915,7 @@ "src/cockpitSubjects.js", "src/cockpitRadar.js", "src/cockpitLook.js", + "src/cockpitOrbital.js", "src/geoDistance.js", "src/data/motionModel.js", "src/ui/panelRailGeometry.js", @@ -981,6 +989,7 @@ "src/cockpitSubjects.js", "src/cockpitRadar.js", "src/cockpitLook.js", + "src/cockpitOrbital.js", "src/geoDistance.js", "src/data/motionModel.js", "src/contactsDetectionPolicy.js", @@ -1033,6 +1042,11 @@ "src/ui/cockpitInstrumentState.js", "src/ui/cockpitRollingValue.js", "src/ui/cockpitCamera.js", + "src/ui/cockpitOrbitalView.js", + "src/data/placeBelow.js", + "src/data/adminBoundaries.js", + "src/data/bundledJson.js", + "src/data/retryableLoad.js", "src/ui/cockpitContext.js", "src/ui/cockpitController.js", "src/ui/cockpitDisplayPortal.js", @@ -1637,6 +1651,7 @@ "src/data/satellitePass.js", "src/sources/tle.js", "src/layers/satellites/catalog.js", + "src/layers/satellites/cockpitSubject.js", "src/layers/satellites/controls.js", "src/layers/satellites/index.js", "src/layers/satellites/ingestion.js", @@ -2411,6 +2426,7 @@ "src/cockpitSubjects.js", "src/cockpitRadar.js", "src/cockpitLook.js", + "src/cockpitOrbital.js", "src/contactsDetectionPolicy.js", "src/contextModePolicy.js", "src/creditKeyboard.js", @@ -2705,6 +2721,7 @@ "src/layers/radio/tuningNoise.js", "src/layers/radio/volume.js", "src/layers/satellites/catalog.js", + "src/layers/satellites/cockpitSubject.js", "src/layers/satellites/controls.js", "src/layers/satellites/index.js", "src/layers/satellites/ingestion.js", @@ -2854,6 +2871,8 @@ "src/ui/cockpitInstrumentState.js", "src/ui/cockpitRollingValue.js", "src/ui/cockpitCamera.js", + "src/ui/cockpitOrbitalView.js", + "src/data/placeBelow.js", "src/ui/cockpitContext.js", "src/ui/cockpitController.js", "src/ui/cockpitDisplayPortal.js", @@ -3675,6 +3694,7 @@ "src/layers/radio/tuningNoise.js", "src/layers/radio/volume.js", "src/layers/satellites/catalog.js", + "src/layers/satellites/cockpitSubject.js", "src/layers/satellites/controls.js", "src/layers/satellites/index.js", "src/layers/satellites/ingestion.js", @@ -4185,6 +4205,7 @@ "src/cockpitSubjects.js", "src/cockpitRadar.js", "src/cockpitLook.js", + "src/cockpitOrbital.js", "src/geoDistance.js", "src/data/motionModel.js", "src/contactsDetectionPolicy.js", diff --git a/src/cameraHandoff.test.mjs b/src/cameraHandoff.test.mjs index a668180fe..1c41139c8 100644 --- a/src/cameraHandoff.test.mjs +++ b/src/cameraHandoff.test.mjs @@ -42,7 +42,7 @@ function ordered(source, needles, label) { test('Cockpit takeover invalidates deferred work before camera cancellation', () => { const enter = cockpitEnter.toString(); ordered(enter, [ - 'if (!info || (!vessel && !entity?.position)) return false;', + 'if (!info || (!vessel && !satellite && !entity?.position)) return false;', 'this.onCameraTakeover?.();', 'this.viewer.camera.cancelFlight();', 'this.viewer.trackedEntity = undefined;', diff --git a/src/cockpitCloudEffects.js b/src/cockpitCloudEffects.js index c9117b7d3..c1cc796b4 100644 --- a/src/cockpitCloudEffects.js +++ b/src/cockpitCloudEffects.js @@ -170,6 +170,18 @@ export function cockpitWeatherEnabledFromStoredValue(value) { return value === '1'; } +/** + * Whether the cloud pass runs for a Cockpit subject's layer. Not in orbit: + * the pass fades out above 24 km (weatherAltitudeFactors), so a satellite + * would pay for it and see nothing. The saved preference is left as it is + * for the next aircraft or bridge; cloud cover from orbit is the Weather + * layer's. + * @param {string|null|undefined} layerId + */ +export function cockpitCloudsShowFor(layerId) { + return layerId !== 'satellites'; +} + /** * Weather-backed volumetric cloud pass that exists only while cockpit mode is * active. It owns no Cesium fog/post-process stages and cannot affect map mode. @@ -207,10 +219,12 @@ class CockpitCloudEffectsController { this.enabled = this.readEnabledPreference(); this.onResize = () => this.resize(); + this.orbit = false; this.onCockpitMode = (event) => { const active = event?.detail?.active ?? document.body.classList.contains('cockpit-mode'); + this.orbit = active && !cockpitCloudsShowFor(event?.detail?.layerId); if (active && this.enabled) this.start(); else this.stop(); }; @@ -344,7 +358,8 @@ class CockpitCloudEffectsController { this.destroyed || !this.enabled || this.frame !== null || - this.suspended + this.suspended || + this.orbit ) return; if (!this.gl) { diff --git a/src/cockpitCloudEffects.test.mjs b/src/cockpitCloudEffects.test.mjs index 18a0ed394..651b3fb27 100644 --- a/src/cockpitCloudEffects.test.mjs +++ b/src/cockpitCloudEffects.test.mjs @@ -2,6 +2,7 @@ import test from 'node:test'; import assert from 'node:assert/strict'; import { cockpitCloudRenderSize, + cockpitCloudsShowFor, cockpitWeatherRefreshDue, cockpitWeatherEnabledFromStoredValue, } from './cockpitCloudEffects.js'; @@ -23,6 +24,13 @@ test('cockpit weather defaults off and enables only from an explicit saved opt-i assert.equal(cockpitWeatherEnabledFromStoredValue('1'), true); }); +test('the cloud pass stays off in orbit and runs for aircraft and bridges', () => { + assert.equal(cockpitCloudsShowFor('satellites'), false); + for (const layerId of ['flights', 'military', 'ais-live-vessels', null]) { + assert.equal(cockpitCloudsShowFor(layerId), true, String(layerId)); + } +}); + test('cockpit weather refreshes after time or meaningful movement', () => { const anchor = { latitude: 30, longitude: -97 }; assert.equal(cockpitWeatherRefreshDue({ diff --git a/src/cockpitLook.js b/src/cockpitLook.js index 8292cde25..e0b133b34 100644 --- a/src/cockpitLook.js +++ b/src/cockpitLook.js @@ -181,3 +181,64 @@ export function lookReadoutParts(look, restPitchDeg) { angleDeg: Math.abs(pitch), }; } + +/** + * The orbital view's off-nadir limit on each axis. The orbital look reuses + * the bridge's `{yawDeg, pitchDeg}` shape over a fixed nadir frame: yaw tilts + * the view east (positive) or west, pitch tilts it north (positive) or + * south. Single 5° steps only; the bridge keeps its own limits. + */ +export const ORBITAL_LOOK_LIMIT_DEG = 45; + +/** Clamp one orbital look axis to ±ORBITAL_LOOK_LIMIT_DEG; NaN rests. */ +function clampOrbitalAxis(deg) { + if (!Number.isFinite(deg)) return 0; + const value = Math.min( + ORBITAL_LOOK_LIMIT_DEG, + Math.max(-ORBITAL_LOOK_LIMIT_DEG, deg), + ); + return value === 0 ? 0 : value; +} + +/** + * Clamp an orbital look to the off-nadir limit on both axes. + * @param {{yawDeg: number, pitchDeg: number}} look East and north tilt. + * @returns {{yawDeg: number, pitchDeg: number}} + */ +export function clampOrbitalLook(look) { + return { + yawDeg: clampOrbitalAxis(look?.yawDeg), + pitchDeg: clampOrbitalAxis(look?.pitchDeg), + }; +} + +/** + * Apply one arrow step to an orbital look: the bridge's stepping on the + * same 5° grid, then the off-nadir clamp. + * @param {{yawDeg: number, pitchDeg: number}} target Current look target. + * @param {{axis: 'yaw'|'pitch', sign: number, stepDeg: number}} step From + * {@link lookKeyStep}. + * @returns {{yawDeg: number, pitchDeg: number}} + */ +export function stepOrbitalLook(target, step) { + return clampOrbitalLook(stepLook(clampOrbitalLook(target), step)); +} + +/** + * The parts of an off-nadir readout, for the Cockpit to word: the north or + * south tilt and the east or west tilt, each null at rest, in whole degrees. + * @param {{yawDeg: number, pitchDeg: number}} look Orbital look target. + * @returns {{northSouth: 'N'|'S'|null, northSouthDeg: number, + * eastWest: 'E'|'W'|null, eastWestDeg: number}} + */ +export function orbitalLookReadoutParts(look) { + const { yawDeg, pitchDeg } = clampOrbitalLook(look); + const north = Math.round(pitchDeg); + const east = Math.round(yawDeg); + return { + northSouth: north > 0 ? 'N' : north < 0 ? 'S' : null, + northSouthDeg: Math.abs(north), + eastWest: east > 0 ? 'E' : east < 0 ? 'W' : null, + eastWestDeg: Math.abs(east), + }; +} diff --git a/src/cockpitLook.test.mjs b/src/cockpitLook.test.mjs index f1f4a239c..27f79e319 100644 --- a/src/cockpitLook.test.mjs +++ b/src/cockpitLook.test.mjs @@ -5,12 +5,16 @@ import assert from 'node:assert/strict'; import { LOOK_COARSE_STEP_DEG, LOOK_STEP_DEG, + ORBITAL_LOOK_LIMIT_DEG, clampLookPitch, + clampOrbitalLook, easeLook, lookIsOffset, lookKeyStep, lookReadoutParts, + orbitalLookReadoutParts, stepLook, + stepOrbitalLook, wrapLookYaw, } from './cockpitLook.js'; @@ -135,3 +139,57 @@ test('the readout names the side, the bearing and the elevation', () => { 'astern', ); }); + +test('an orbital look steps 5° per arrow and stops at 45° on each axis', () => { + let look = { yawDeg: 0, pitchDeg: 0 }; + for (let index = 0; index < 3; index += 1) + look = stepOrbitalLook(look, lookKeyStep('ArrowUp')); + assert.deepEqual(look, { yawDeg: 0, pitchDeg: 15 }); + look = stepOrbitalLook(look, lookKeyStep('ArrowRight')); + assert.deepEqual(look, { yawDeg: 5, pitchDeg: 15 }); + for (let index = 0; index < 20; index += 1) { + look = stepOrbitalLook(look, lookKeyStep('ArrowDown')); + look = stepOrbitalLook(look, lookKeyStep('ArrowLeft')); + } + assert.deepEqual(look, { + yawDeg: -ORBITAL_LOOK_LIMIT_DEG, + pitchDeg: -ORBITAL_LOOK_LIMIT_DEG, + }); + assert.deepEqual(clampOrbitalLook({ yawDeg: 90, pitchDeg: NaN }), { + yawDeg: 45, + pitchDeg: 0, + }); + assert.deepEqual(clampOrbitalLook({ yawDeg: 180, pitchDeg: -60 }), { + yawDeg: 45, + pitchDeg: -45, + }); +}); + +test('the orbital readout names north or south and east or west', () => { + assert.deepEqual(orbitalLookReadoutParts({ yawDeg: 15, pitchDeg: 10 }), { + northSouth: 'N', + northSouthDeg: 10, + eastWest: 'E', + eastWestDeg: 15, + }); + assert.deepEqual(orbitalLookReadoutParts({ yawDeg: -5, pitchDeg: 0 }), { + northSouth: null, + northSouthDeg: 0, + eastWest: 'W', + eastWestDeg: 5, + }); + assert.equal( + orbitalLookReadoutParts({ yawDeg: 0, pitchDeg: -45 }).northSouth, + 'S', + ); +}); + +test('the bridge look keeps its own limits beside the orbital clamp', () => { + const look = stepLook({ yawDeg: 45, pitchDeg: 45 }, lookKeyStep('ArrowUp')); + assert.deepEqual(look, { yawDeg: 45, pitchDeg: 50 }); + assert.equal( + stepLook({ yawDeg: 45, pitchDeg: 0 }, lookKeyStep('ArrowRight', true)) + .yawDeg, + 90, + ); +}); diff --git a/src/cockpitMarkup.test.mjs b/src/cockpitMarkup.test.mjs index aa06193ba..06db3aeff 100644 --- a/src/cockpitMarkup.test.mjs +++ b/src/cockpitMarkup.test.mjs @@ -79,7 +79,7 @@ test('Cockpit has one reset action beside its bottom exit path', () => { assert.doesNotMatch(html, /id="cockpit-exit"/); assert.match( html, - /id="map-view-switch"[^>]*aria-label="Exit cockpit view"[^>]*aria-keyshortcuts="Escape C"[\s\S]*?close_fullscreen[\s\S]*?EXIT COCKPIT/, + /id="map-view-switch"[^>]*aria-label="Exit cockpit view"[^>]*aria-keyshortcuts="Escape"[\s\S]*?close_fullscreen[\s\S]*?EXIT COCKPIT/, ); const topCenterActions = html.match( /