@rr0/ufoathome 0.127.3 → 0.128.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist-embed-interview/InterviewMessages_es-CNKjrohj.js +1 -0
  2. package/dist-embed-interview/InterviewMessages_fr-BP99Pg7g.js +1 -0
  3. package/dist-embed-interview/InterviewMessages_it-DTIrw8wW.js +1 -0
  4. package/dist-embed-interview/rr0-interview.mjs +5 -5
  5. package/dist-embed-scene/RailwaySystem-IcloRjw9.js +41 -0
  6. package/dist-embed-scene/{SceneNames_es-B9tudMDH.js → SceneNames_es-BITaYGB1.js} +1 -1
  7. package/dist-embed-scene/{SceneNames_fr-DAd-g0yB.js → SceneNames_fr-Bdk_h-Pr.js} +1 -1
  8. package/dist-embed-scene/{SceneNames_it-BLLX--oG.js → SceneNames_it-DhE0SScp.js} +1 -1
  9. package/dist-embed-scene/browser-_Ncw3Jhn.js +1 -0
  10. package/dist-embed-scene/rr0-scene.mjs +303 -300
  11. package/dist-embed-scene/{sightingSchema-v2l1p6Ld.js → sightingSchema-W7ivL-LH.js} +1 -1
  12. package/dist-embed-sighting/RailwaySystem-SElJhlLh.js +41 -0
  13. package/dist-embed-sighting/{SceneNames_es-VHJ-mGWu.js → SceneNames_es-Zb4vw-Vp.js} +1 -1
  14. package/dist-embed-sighting/{SceneNames_fr-BtjbcaRx.js → SceneNames_fr-C6_IIN2c.js} +1 -1
  15. package/dist-embed-sighting/{SceneNames_it-Ck8f90Z6.js → SceneNames_it-D7GivBq2.js} +1 -1
  16. package/dist-embed-sighting/browser-_Ncw3Jhn.js +1 -0
  17. package/dist-embed-sighting/rr0-sighting.mjs +296 -293
  18. package/dist-embed-sighting/{sightingSchema-v2l1p6Ld.js → sightingSchema-W7ivL-LH.js} +1 -1
  19. package/dist-embed-sighting-editor/{AdsbLolArchiveProvider-BtbGVTLo.js → AdsbLolArchiveProvider-DAFMMxZ9.js} +1 -1
  20. package/dist-embed-sighting-editor/{BodyEditor-BAT3yx6v.js → BodyEditor-T_1Jhs5n.js} +1 -1
  21. package/dist-embed-sighting-editor/CaseEditorMessages_es-DwO2w2Vc.js +1 -0
  22. package/dist-embed-sighting-editor/CaseEditorMessages_fr-iFzha0wM.js +1 -0
  23. package/dist-embed-sighting-editor/CaseEditorMessages_it-CjdJSAvo.js +1 -0
  24. package/dist-embed-sighting-editor/{ContrailSystem-B24rkkhS.js → ContrailSystem-DAHnNwJY.js} +1 -1
  25. package/dist-embed-sighting-editor/CoverageAssessor-24x89QSu.js +1 -0
  26. package/dist-embed-sighting-editor/GLTFLoader-BrlMonfv.js +1 -0
  27. package/dist-embed-sighting-editor/HeadlightSystem-9Ve6quO7.js +34 -0
  28. package/dist-embed-sighting-editor/{HynekAssessor-DVFjzROZ.js → HynekAssessor-CspF0udm.js} +1 -1
  29. package/dist-embed-sighting-editor/{InterviewEditorElement-CcEomZL0.js → InterviewEditorElement-Dm-ghjgg.js} +7 -9
  30. package/dist-embed-sighting-editor/InterviewMessages_en-yw5Qfw-6.js +1 -0
  31. package/dist-embed-sighting-editor/InterviewMessages_es-CNKjrohj.js +1 -0
  32. package/dist-embed-sighting-editor/InterviewMessages_fr-BP99Pg7g.js +1 -0
  33. package/dist-embed-sighting-editor/InterviewMessages_it-DTIrw8wW.js +1 -0
  34. package/dist-embed-sighting-editor/{LaunchEditor-BXDWiKWm.js → LaunchEditor-DfbahkM1.js} +1 -1
  35. package/dist-embed-sighting-editor/ModelSource-BjAOa9Br.js +1 -0
  36. package/dist-embed-sighting-editor/{ModelThumbnails-CGklRkoB.js → ModelThumbnails-B8ONo6Zq.js} +1 -1
  37. package/dist-embed-sighting-editor/{ModelViewer-Bg9kN_Zq.js → ModelViewer-BRBnm1f4.js} +1 -1
  38. package/dist-embed-sighting-editor/RailwaySystem-CO0S5Tvo.js +41 -0
  39. package/dist-embed-sighting-editor/{RoadMarkings-CVibbxgC.js → RoadMarkings-ysQVkGP6.js} +1 -1
  40. package/dist-embed-sighting-editor/{SceneNames_es-4pppn42v.js → SceneNames_es-BJhUPnW8.js} +1 -1
  41. package/dist-embed-sighting-editor/{SceneNames_fr-odZ6uYWU.js → SceneNames_fr-DXA1PSOW.js} +1 -1
  42. package/dist-embed-sighting-editor/{SceneNames_it-lXfB7y6i.js → SceneNames_it-CKVqa3DF.js} +1 -1
  43. package/dist-embed-sighting-editor/{SightingEditorMessages_es-C2q5UZrw.js → SightingEditorMessages_es-j9jNoZ69.js} +2 -2
  44. package/dist-embed-sighting-editor/SightingEditorMessages_fr-ClasHdht.js +12 -0
  45. package/dist-embed-sighting-editor/SightingEditorMessages_it-CgRkHcvD.js +12 -0
  46. package/dist-embed-sighting-editor/{SightingFileEditor-7inIgp24.js → SightingFileEditor-CEjimNPM.js} +1 -1
  47. package/dist-embed-sighting-editor/{TraceSystem-CZSZY6ZM.js → TraceSystem-BJbyw7Wf.js} +2 -2
  48. package/dist-embed-sighting-editor/{WaterSystem-Bd010I79.js → WaterSystem-DprmGdDo.js} +1 -1
  49. package/dist-embed-sighting-editor/rr0-sighting-editor.mjs +429 -357
  50. package/dist-embed-sighting-editor/{sightingSchema-v2l1p6Ld.js → sightingSchema-W7ivL-LH.js} +1 -1
  51. package/dist-embed-sighting-editor/surroundingsSources-C67enaVE.js +1 -0
  52. package/dist-embed-sighting-editor/trafficRuntime-oYuU__pd.js +2 -0
  53. package/package.json +1 -1
  54. package/dist-embed-interview/InterviewMessages_es-D5d2JVA3.js +0 -1
  55. package/dist-embed-interview/InterviewMessages_fr-CmScqfza.js +0 -1
  56. package/dist-embed-interview/InterviewMessages_it-2SNw5xMp.js +0 -1
  57. package/dist-embed-scene/RailwaySystem-BSqu6iHY.js +0 -41
  58. package/dist-embed-sighting/RailwaySystem-BXRi4IAz.js +0 -41
  59. package/dist-embed-sighting-editor/CaseEditorMessages_es-CNLEMPjy.js +0 -1
  60. package/dist-embed-sighting-editor/CaseEditorMessages_fr-DN3xxn9o.js +0 -1
  61. package/dist-embed-sighting-editor/CaseEditorMessages_it-B6aG-baK.js +0 -1
  62. package/dist-embed-sighting-editor/CoverageAssessor-BPhdv7QL.js +0 -1
  63. package/dist-embed-sighting-editor/GLTFLoader-C7miE2gT.js +0 -1
  64. package/dist-embed-sighting-editor/HeadlightSystem-DaWqNslK.js +0 -34
  65. package/dist-embed-sighting-editor/InterviewMessages_en-cs-wWpmz.js +0 -1
  66. package/dist-embed-sighting-editor/InterviewMessages_es-D5d2JVA3.js +0 -1
  67. package/dist-embed-sighting-editor/InterviewMessages_fr-CmScqfza.js +0 -1
  68. package/dist-embed-sighting-editor/InterviewMessages_it-2SNw5xMp.js +0 -1
  69. package/dist-embed-sighting-editor/ModelSource-gIw80dOv.js +0 -1
  70. package/dist-embed-sighting-editor/RailwaySystem-BCDMPAEx.js +0 -41
  71. package/dist-embed-sighting-editor/SightingEditorMessages_fr-DyELrz-P.js +0 -12
  72. package/dist-embed-sighting-editor/SightingEditorMessages_it-CUKdtgr1.js +0 -12
  73. package/dist-embed-sighting-editor/surroundingsSources-98rSCu2Y.js +0 -1
  74. package/dist-embed-sighting-editor/trafficRuntime-Dk4XdgcY.js +0 -2
@@ -1,12 +0,0 @@
1
- const e={color:"Colore",transparency:"Trasparenza",halo:"Alone",blur:"Sfocatura",brightness:"Brillantezza",shapeTitle:"Nome",utcOffset:"Fuso orario",cloudBase:"Base delle nuvole",elevation:"Altitudine",heightAboveGround:"Altezza dal suolo",duration:"Durata",placeName:"Luogo",latitude:"Latitudine",longitude:"Longitudine",heading:"Orientamento",pitch:"Inclinazione",roll:"Rollio",sway:"Oscillazione a riposo",swayTitle:"Quanto il corpo che regge lo strumento muove la vista quando non cammina: 1 per una persona in piedi, 0 per un treppiede. Vuoto: 1 (0 se il resoconto dice che l'osservatore era paralizzato)",lightPollution:"Cielo notturno",lightPollutionTitle:"Lo zenit di una notte senza Luna in questo luogo, in magnitudini per secondo d'arco quadrato, come lo legge uno Sky Quality Meter o lo dà l'atlante mondiale della brillanza artificiale del cielo (Falchi et al. 2016, lightpollutionmap.info, «SQM»). 22 è un cielo naturale; una periferia è intorno a 19, un centro città a 17. Vuoto: un cielo naturale",observationTime:"Inizio dell'osservazione",observationEndTime:"Fine dell'osservazione",assessmentGroup:"Valutazione",assessmentNames:{coverage:"Dati dell'osservatore"},assessmentVerdicts:{"hynek.nl":"NL — luce notturna","hynek.dd":"DD — disco diurno","hynek.rv":"RV — radar-visivo","hynek.ce1":"IR1 — incontro ravvicinato","hynek.ce2":"IR2 — con traccia fisica","hynek.ce3":"IR3 — con entità"},timeQualifierApproximate:"Approssimativa",timeQualifierUncertain:"Incerta",timeQualifierBoth:"Incerta e approssimativa",timeSeasonSpring:"Primavera",timeSeasonSummer:"Estate",timeSeasonAutumn:"Autunno",timeSeasonWinter:"Inverno",summaryGroups:{observation:"Osservazione",location:"Posizione",temporal:"Tempo",weather:"Meteo",sound:"Suono"},summaryGroup:"Riepilogo",summaryDescription:"Descrizione",closeDescription:"Chiudi la descrizione",observerGroup:"Osservatore",observerId:"ID",observerTitle:"Titolo",observerLastName:"Cognome",observerFirstNames:"Nomi",sightingId:"ID",tags:"Etichette",cloudCover:"Copertura nuvolosa",highCloudCover:"Nubi di ghiaccio (cirri)",focalLength:"Lunghezza focale",fieldOfView:"Campo visivo",aperture:"Apertura",exposure:"Esposizione",focusDistance:"Messa a fuoco a",iceCrystalAlignment:"Allineamento dei cristalli",rareIceCrystals:"Cristalli rari",cloudDarkness:"Oscurità delle nuvole",precipitationType:"Precipitazioni",precipitationNone:"Nessuna",precipitationRain:"Pioggia",precipitationSnow:"Neve",precipitationHail:"Grandine",precipitationIntensity:"Intensità",windDirection:"Direzione del vento",windSpeed:"Velocità del vento",storm:"Temporale",cloudsGroup:"Nuvole",precipitationGroup:"Precipitazioni",windGroup:"Vento",soundKind:"Suono",soundNone:"Nessuno (silenzioso)",soundHum:"Ronzio",soundWhistle:"Fischio",soundRumble:"Rombo",soundCrackle:"Crepitio",soundVolume:"Volume",soundPitch:"Tono",soundSrc:"Registrazione",instrument:"Osservato con",filter:"Davanti",filterNone:"niente",filterSolarVisual:"un filtro solare per l'occhio (occhiali da eclissi, densità 5)",filterSolarPhoto:"una pellicola solare per fotocamera (densità 3,8)",decorAircraft:"Aeromobile",decorEntity:"Essere",decorAltitude:"Altitudine",decorLights:"Luci",decorLightsNone:"nessuna",decor:"Ambiente",decorBuilding:"Edificio",decorTree:"Albero",decorShrub:"Cespuglio",decorBridge:"Ponte",decorWire:"Linea aerea",decorCrop:"Filare di coltura",decorTerrace:"Terrazzamento",decorMound:"Mucchio di pietre",decorWall:"Muretto a secco",decorStreetlight:"Lampione",decorTrafficLight:"Semaforo",decorCrossing:"Attraversamento pedonale",decorRoadSign:"Segnale stradale",decorVehicle:"Veicolo",decorObserver:"Altro osservatore",decorEast:"Distanza a est",decorNorth:"Distanza a nord",decorHeading:"Orientamento",decorColor:"Colore",decorLit:"Acceso",decorTitle:"Nome",milestones:"Momenti",milestoneLabel:"Etichetta",milestoneNote:"Cosa succede",addMilestone:"Dai un nome a questo momento",deleteMilestone:"Elimina momento",goToMilestone:"Vai a questo momento",decorWidth:"Larghezza",decorLength:"Lunghezza",decorHeight:"Altezza",decorModel:"Modello 3D",decorModelAdvanced:"Modello da un indirizzo",decorModelUrl:"Indirizzo glTF/GLB",decorModelTitle:"Nome del modello",decorModelAuthor:"Autore",decorModelLicense:"Licenza",decorModelSource:"Provenienza",decorObserverSide:"Posizione dell'osservatore",decorObserverSideNone:"Non presente",decorSideFront:"Davanti",decorSideBehind:"Dietro",decorSideLeft:"Sinistra",decorSideRight:"Destra",decorSideFrontLeft:"Davanti a sinistra",decorSideFrontRight:"Davanti a destra",decorSideBehindLeft:"Dietro a sinistra",decorSideBehindRight:"Dietro a destra"},a={...e,oval:"Ovale",polygon:"Poligono",addVertex:"Aggiungi vertice",deleteVertex:"Elimina vertice",notAPolygon:"Seleziona una sola forma poligonale",tooFewVertices:"Una forma ha bisogno di almeno 3 punti",shape:"Forma",apparentWidth:"Larghezza apparente",realWidth:"Larghezza reale",distance:"Distanza",sizeLock:"Mantieni",lockNone:"niente",lockApparent:"la larghezza apparente",lockReal:"la larghezza reale",lockDistance:"la distanza",apparentSize:"{moons}× la Luna",utcOffsetPlaceholder:"dalla longitudine",realSizeBetween:"La scena delimita quella larghezza: tra {min} e {max} m, in base a ciò che attraversa",realSizeAtLeast:"La scena delimita quella larghezza: almeno {min} m, in base a ciò dietro cui passa",realSizeAtMost:"La scena delimita quella larghezza: al massimo {max} m, in base a ciò davanti a cui passa",realSizeUnknown:"Nulla nella scena delimita quella larghezza: è solo ciò che la distanza implica",realSizeOutside:" — la larghezza qui sopra ne è fuori",blurBound:"Sfocato attraverso questo obiettivo: più vicino di {max} m",blurBoundNoInstrument:"La sfocatura a occhio nudo non delimita alcuna distanza — un occhio non ha un diaframma con cui andare fuori fuoco",blurBoundNotAtInfinity:"La sfocatura delimita una distanza solo per un obiettivo messo a fuoco all'infinito: questo è a fuoco a {focus} m, il che sfoca da entrambi i lati",realSizeContradiction:"Contraddizione: gli attraversamenti dichiarati non possono essere tutti veri",realDistanceHere:" — cioè qui tra {min} e {max} m",clearDistanceHypothesis:"Ritira l'ipotesi di distanza",clearDistanceHypothesisTitle:"Torna a ciò che la registrazione stabilisce",depthStated:"Disegnato a {m} m, come dichiara la registrazione",depthHypothesis:"Disegnato a {m} m: la tua ipotesi — ciò che la scenografia ne nasconde è ciò che perderebbe una cosa così lontana",depthDerived:"Disegnato a {m} m, in base alla camminata stessa dell'osservatore",depthBounded:"Disegnato a {m} m, in base a ciò dietro e davanti a cui passa",depthConventional:"Disegnato a {m} m per convenzione: nulla nella registrazione stabilisce una distanza",addShape:"Aggiungi forma",deleteShape:"Elimina forma",play:"Riproduci",pause:"Pausa",noDuration:"Nessuna durata di osservazione",previousKeyframe:"Fotogramma chiave precedente",nextKeyframe:"Fotogramma chiave successivo",keyframeMark:"Fotogramma chiave",shapesTrack:"forme",observerTrack:"osservatore",weatherTrack:"meteo",soundTrack:"suono",group:"Raggruppa",ungroup:"Separa",bringToFront:"Porta in primo piano",sendToBack:"Porta in fondo",contextMenuDelete:"Elimina",onlyOneShape:"C'è una sola forma",alreadyAtFront:"Questa forma è già in primo piano",alreadyAtBack:"Questa forma è già in fondo",needTwoShapesToGroup:"Seleziona almeno due forme per raggrupparle",notGrouped:"Questa forma non fa parte di un gruppo",multipleShapesSelected:"Più forme selezionate — selezionane una sola per modificare questo",samplingRate:"Frequenza di campionamento",currentPosition:"Posizione attuale",switchToElapsed:"clicca per mostrare il tempo trascorso",switchToClockTime:"clicca per mostrare l'ora del giorno",durationPlaceholder:"durata dell'osservazione",durationImprecise:"Queste date non determinano con sufficiente precisione una durata — inseriscila manualmente.",export:"Salva",identityHint:"Nomina qualcuno solo se vi ha acconsentito o ha pubblicato lui stesso la propria testimonianza; altrimenti bastano le iniziali.",identityAsk:"Questa registrazione nomina o colloca una persona. Rispondi di ciò che pubblichi: nomina qualcuno solo se vi ha acconsentito, o se ha pubblicato lui stesso la propria testimonianza. Altrimenti bastano le iniziali.",identityLastName:"Cognome: {value}",identityFirstNames:"Nome: {value}",identityNameInId:"Nome in un identificativo: {value}",identityNameInText:"Nome nel testo: {value}",identityAddress:"Indirizzo: {value}",identityEmail:"Indirizzo e-mail: {value}",identityPhone:"Numero di telefono: {value}",identityInitials:"Sostituisci con le iniziali",identityKeep:"Salva comunque",identityBack:"Torna indietro",importFile:"Carica file JSON",importUrl:"Oppure carica da URL",importUrlPlaceholder:"https://…/sighting.json",importButton:"Carica",importError:"Impossibile caricare questa registrazione — controlla il file o l'URL e riprova.",importErrorCors:`Questo indirizzo risponde, ma il browser non ha il permesso di leggerlo da questa pagina. Il file in sé va bene: è il suo server che deve inviarlo con l'intestazione "Access-Control-Allow-Origin: *". Se il server non è tuo, è questo che devi chiedere al suo amministratore.`,importErrorMixedContent:"Una pagina sicura non può caricare un indirizzo che inizia con http://. Usa https:// se quel server lo offre.",importErrorUnreachable:"Nulla ha risposto a questo indirizzo. Controlla come è scritto e di essere connesso.",importErrorStatus:"Quel server ha risposto con un errore ({status}). Probabilmente l'indirizzo è sbagliato o il file è stato spostato.",importErrorMalformed:"Questo indirizzo ha risposto, ma ciò che è tornato non è una registrazione.",record:"Registra",stop:"Ferma",according:"secondo",sourceElevation:"Rilievo",sourceImagery:"Immagini",sourceAircraft:"Traffico aereo",placeNamePlaceholder:"Valensole, Francia",searchPlace:"Localizza",placeMatch:"Corrispondenze",placeSearching:"Ricerca del luogo…",placeMatchFound:"luogo trovato",placeMatchesFound:"luoghi trovati",placeNotFound:"Nessun luogo con questo nome",placeSearchFailed:"Ricerca dei luoghi momentaneamente non disponibile",utcOffsetNoZone:"Nessun fuso indica questo scarto quel giorno",utcOffsetImplausible:"Questo fuso orario non corrisponde alla longitudine inserita, la cui ora solare è UTC{solar} — eppure la scena e il rilevamento meteo obbediscono a ciò che è dichiarato qui. Svuota il campo per ricavarlo dalla longitudine.",timeZoneManual:"sconosciuto",altitudeAboveSeaLevel:"Altitudine dell'osservatore sul livello del mare — il suolo del luogo inserito ne fissa il minimo: un osservatore sulle Alpi non è a 0 m.",groundAt:"suolo a {m} m",headingPlaceholder:"sconosciuto",edtfInvalid:"Data/ora EDTF non valida (es. 1965-07-01T05:00, 2025-06?, 2025~).",edtfPlaceholder:"AAAA-MM-GGThh:mm[?~%] o hh:mm",observationTimeHint:"EDTF — es. 1965-07-01T05:00, 2025-06? (incerto), 2025~ (approssimativo), o solo 05:00 se la data non è nota",observationEndTimeHint:"EDTF — es. 1965-07-01T05:10, 2025-06? (incerto), 2025~ (approssimativo), o solo 05:10 se la data non è nota",presetsGroupLabel:"Forma dell'UFO",description:"Descrizione",tagsPlaceholder:"separati da virgole",weather:"Meteo",shapeGroup:"Fenomeno",shapesSubgroup:"Forme",bodiesSubgroup:"Corpi",launchesSubgroup:"Lanci",soundGroup:"Suono",temporalGroup:"Momento",fileGroup:"File",fileLoading:"Caricamento dell'editor…",weatherEditedAsk:"Questa modifica tocca il meteo, un dato letto dinamicamente da {source}. Vuoi smettere di leggerlo da {source}?",weatherEditedStop:"Smetti di leggerlo",weatherEditedKeep:"Continua a leggerlo (annulla la mia modifica)",fileEditorLabel:"La registrazione come testo JSON",fileSearchPhrases:{Find:"Cerca",Replace:"Sostituisci",next:"successivo",previous:"precedente",all:"tutti","match case":"maiuscole","by word":"parola intera",regexp:"regexp",replace:"sostituisci","replace all":"sostituisci tutto",close:"chiudi","current match":"corrispondenza corrente","on line":"alla riga","replaced $ matches":"$ corrispondenze sostituite","replaced match on line $":"corrispondenza sostituita alla riga $","Go to line":"Vai alla riga",go:"vai"},timeQualifierExact:"Esatta",durationPrecise:"precisa",durationIso:"imprecisa",durationModeTitle:"Dire la durata esattamente, o come è stata enunciata: circa, tra due durate",durationInvalid:"Non è una durata: PT10M, PT1H30M, PT5M/PT10M…",durationHelpTitle:"Che cosa accetta il testo (EDTF)",durationHelpLines:`PT45S — 45 secondi
2
- PT10M — 10 minuti
3
- PT1H30M — 1 ora 30 minuti
4
- PT5M/PT10M — tra 5 e 10 minuti
5
- Terminare con ? se incerto, ~ se approssimativo, % per entrambi
6
- 1965-?07 — il dubbio può riguardare anche una parte`,durationChosen:"(simulata: {value})",accountView:"Resoconto",accountView2d:"2D · forme",accountView3d:"3D · corpi",accountViewHint:"Ciò che mostra il render e ciò che si modifica: le forme che l'osservatore ha disegnato, o i corpi che ha detto che fossero",datePrecise:"precisa",dateEdtf:"imprecisa",dateHelpTitle:"Che cosa accetta il testo (EDTF)",dateHelpLines:`1965 — un anno
7
- 1965-07 — un mese
8
- 1965-21 — una stagione (21 primavera, 22 estate, 23 autunno, 24 inverno)
9
- 1965-07-01 — un giorno
10
- 1965-07-01T05:00 — un giorno e un'ora
11
- 05:00 — un'ora, data sconosciuta
12
- Terminare con ? se incerto, ~ se approssimativo, % per entrambi`,edtfModeTitle:"Scrivi invece una data imprecisa: solo un anno, un mese, un'ora senza data",locationGroup:"Posizione",observationGroup:"Riepilogo",weatherWhilePlaying:"Metti in pausa la registrazione per indicare il tempo — mentre scorre, l'istante in cui verrebbe scritto si sposta",weatherInferred:"Dai rilevamenti",weatherInferredTitle:"Il meteo non è un resoconto: è un fatto misurabile, rilevato per la data, l'ora e il luogo dell'osservazione. Deseleziona per indicare le condizioni riferite dall'osservatore, che allora prevalgono sul rilevamento.",weatherLookingUp:"Ricerca del rilevamento…",weatherNeedsDateAndPlace:"Servono una data completa e un luogo per cercare il rilevamento",weatherNeedsDate:"Serve una data completa (anno, mese e giorno) per cercare i rilevamenti meteo",weatherNeedsPlace:"Serve un luogo con coordinate per cercare i rilevamenti meteo",weatherNoRecord:"Nessun rilevamento per questa data e questo luogo",weatherLookupFailed:"Rilevamenti meteo momentaneamente irraggiungibili",lightPollutionLookingUp:"Consultazione dell'atlante…",lightPollutionFound:"{artificial} µcd/m² di luce artificiale,",lightPollutionNatural:"Nessuna luce artificiale qui,",lightPollutionOutside:"Fuori dall'atlante (da 85°N a 60°S),",lightPollutionFailed:"Atlante al momento irraggiungibile",lightPollutionTooEarly:"L'atlante descrive il {atlasYear}; il cielo del {year} era più buio, indicarlo se è noto",instrumentOutOfPeriod:"{name} — non di quest'epoca",instrumentCategoryEye:"Occhio nudo",instrumentCategoryCamera:"Fotocamere",instrumentCategoryDslr:"Reflex digitali",instrumentCategoryPhone:"Telefoni",instrumentCategoryBinoculars:"Binocoli",instrumentCategoryTelescope:"Telescopi",instrumentNotYetOnSale:"Non esisteva ancora nel {year} (in vendita dal {from})",instrumentNoLongerOnSale:"Non esisteva più nel {year} (in vendita fino al {to})",filterNotForInstrument:"Non utilizzabile con questo strumento",unitMillimetres:"mm",unitDegrees:"°",fieldOfViewReadout:"{deg}° di campo",soundSrcPlaceholder:"URL di una registrazione reale",referenceGroup:"Foto",reference:"Foto",referenceTitle:"Nome",referenceSrc:"Indirizzo",referenceSrcPlaceholder:"https://…/photo.jpg",referenceKind:"Tipo",referencePhoto:"Foto",referencePanorama:"Panorama (360°)",referenceCredit:"Crediti",referenceCreditUrl:"Link dei crediti",referenceT:"Scattata a",referenceDrawing:"Disegno sopra",referenceOpacity:"Opacità",referenceHeading:"Direzione",referencePitch:"Beccheggio",referenceRoll:"Rollio",referenceFov:"Campo verticale",referenceUsePose:"Usa la posa dell'osservatore",addReferenceUrl:"Aggiungi da un indirizzo",addReferenceFile:"Aggiungi un file",deleteReference:"Elimina foto",referenceEmbedded:"{kb} kB incorporati nella registrazione — un indirizzo la terrebbe leggera",referenceUnreachable:"Impossibile caricare la foto: controlla l'indirizzo e che il suo sito permetta ad altri siti di leggerla",referenceRegisterHint:"Trascina per ruotare la foto, rotellina per cambiarne il campo; «Aggiungi un punto di riferimento» per indicare un dettaglio sulla foto, poi lo stesso nel rendering",referenceLandmarkPicture:"Punto di riferimento {n}: clicca il punto sulla foto",referenceLandmarkScene:"Punto di riferimento {n}: clicca lo stesso punto nel rendering",referenceLandmarkOffPicture:"Questo clic non cade sulla foto",referenceNotLoaded:"La foto non è ancora arrivata",referenceLandmarksFit:"{n} punti di riferimento — scarto medio di {deg}°",referenceLandmarks:"Punti di riferimento",addReferenceLandmark:"Aggiungi un punto di riferimento",deleteReferenceLandmark:"Elimina punto di riferimento",referenceLandmarkLabel:"Nome",referenceLandmarkLabelPlaceholder:"Albero che copre, recinzione…",referenceAdoptPose:"Adotta come posa dell'osservatore",referenceAdoptRationale:"Misurato sulla foto «{title}»: {n} punti di riferimento allineati, {deg}° di scarto residuo",referenceStreetSearch:"Foto stradali nei dintorni",referenceStreetSearching:"Ricerca di foto scattate nei dintorni…",referenceStreetNone:"Nessuna foto stradale entro {m} m (Panoramax)",referenceStreetFailed:"Impossibile raggiungere Panoramax",referenceStreetAdd:"Aggiungi",traceImport:"Tracciati dell'investigatore (KML, KMZ)",trace:"Tracciato",deleteTrace:"Elimina il tracciato",traceTitle:"Nome",traceSource:"Fonte",traceImported:"{n} importato/i da {name}.",traceSkipped:"Escluso: {what}.",traceNone:"Nessuna linea, luogo o contorno in questo file.",traceFailed:"Impossibile leggere questo file.",traceKindPoint:"luogo",traceKindLine:"linea",traceKindPolygon:"contorno",referenceStreetItem:"{distance} m a {bearing}°, {date}{panorama}",referenceStreetPanorama:" — 360°",referenceStreetTitle:"Foto stradale a {distance} m a {bearing}°, {date}",skyLine:"Cielo: {parts}",skyStarsEye:"stelle fino alla magnitudine {limit}, il limite che un occhio raggiungeva sotto questo cielo",skyStarsDeeper:"stelle fino alla magnitudine {limit} attraverso un {device} — {gain} magnitudini oltre le {eye} raggiunte dagli occhi dell'osservatore",skyStarsShallower:"stelle fino alla magnitudine {limit} attraverso un {device} — {gain} magnitudini al di qua delle {eye} raggiunte dagli occhi dell'osservatore",skyStarsCatalogue:", disegnate fino a {catalogue}, dove si ferma il catalogo di questo progetto",skyStarsNone:"nessuna stella si distingueva in un cielo così chiaro",skyDetails:"Mostra i rilevamenti completi",skyDetailsHide:"Nascondi i rilevamenti",skyShowerActive:"{name} — radiante a {altitude}° sopra l'orizzonte, {bearing} — circa {rate}/h sotto questo cielo, su un fondo sporadico di {sporadic}/h",skyShowerBelowHorizon:"{name} è attivo, ma il suo radiante è sotto l'orizzonte — non ha potuto produrre nulla",skyNothingActive:"nessuno sciame meteorico attivo in questa data — un fondo sporadico di circa {sporadic}/h",showMeteor:"Mostrami una meteora",skyComet:"La {name}, magnitudine {magnitude}, a {altitude}° sopra l'orizzonte {bearing}, coda lunga {tail}°",skyCometNoTail:"La {name}, magnitudine {magnitude}, a {altitude}° sopra l'orizzonte {bearing}",skyCometBelowHorizon:"La {name} c'era, di magnitudine {magnitude}, ma sotto l'orizzonte — nessuno qui l'ha vista",skyCometInDaylight:"La {name}, magnitudine {magnitude}, a {altitude}° sopra l'orizzonte {bearing} — ma a soli {elongation}° dal Sole",showComet:"Mostrami la cometa",skyNova:"La {name}, una stella nuova di magnitudine {magnitude}, a {altitude}° sopra l'orizzonte {bearing}",skyNovaBelowHorizon:"La {name} brillava di magnitudine {magnitude}, ma sotto l'orizzonte: nessuno qui l'ha vista",showNova:"Mostrami la stella nuova",skyEclipsePartial:"Eclissi di Sole: la Luna nasconde il {percent} % del Sole alle {time}, a {altitude}° sopra l'orizzonte {bearing}",skyEclipseTotal:"Eclissi totale di Sole: il Sole è interamente nascosto dalle {time} per {duration}, a {altitude}° sopra l'orizzonte {bearing}",skySupermoon:"Luna piena a {distance} km: {diameter}° di larghezza, il {percent} % in più che alla distanza media — una «superluna», e non più grande all'orizzonte che in alto",skyMicromoon:"Luna piena a {distance} km: {diameter}° di larghezza, il {percent} % in meno che alla distanza media — una «microluna», e non più piccola all'orizzonte che in alto",skyRedMoon:"La «lune rousse»: la Luna piena della lunazione che segue la Pasqua, a {altitude}° sopra l'orizzonte {bearing} — bassa, quindi arrossata dall'aria che attraversa, e né più grande né più luminosa di un'altra",skySatellitePasses:"{count} satelliti hanno attraversato questo cielo abbastanza luminosi da essere visti, il più luminoso {name}, magnitudine {magnitude}, a {altitude}° sopra l'orizzonte {bearing} alle {time}",skySatellitePassesOne:"un satellite ha attraversato questo cielo abbastanza luminoso da essere visto: {name}, magnitudine {magnitude}, a {altitude}° sopra l'orizzonte {bearing} alle {time}",skySatelliteTrain:"tra cui un treno di {count} Starlink lanciati il {date}",skySatellitePassesNone:"secondo gli elementi orbitali archiviati per quella data, nessun satellite illuminato ha attraversato questo cielo abbastanza luminoso da essere visto",skySatelliteElementsGap:"nessun elemento orbitale archiviato vicino a quella data",skyReentries:"rientri registrati: {list}",skyReentriesMore:"altri {count}",skyReentrySeen:"{name} è ricaduto alle {time}, visto da {place} (a {distance} km)",skyReentryObserved:"{name} è ricaduto alle {time}, visto",skyReentryOffset:", a {minutes} min dall'osservazione",skyReentryPredicted:"{name} è ricaduto verso le {time} ± {hours} h, non si sa dove",skyReentryDay:"{name} è ricaduto il {date} (UTC), senza ora né luogo noti",skyFireballs:"{count} bolidi registrati dalla Global Meteor Network, il più luminoso di magnitudine {magnitude} alle {time}, a {altitude}° di altezza {bearing}, a {distance} km ({stations} stazioni)",skyFireballsOne:"un bolide registrato dalla Global Meteor Network: magnitudine {magnitude} alle {time}, a {altitude}° di altezza {bearing}, a {distance} km ({stations} stazioni)",showFireball:"Mostrami il bolide",showSatellite:"Mostrami un satellite",skyOpticsPossible:"nubi di ghiaccio sufficienti, intorno {source}, per {forms}",skyOpticsAlignment:" — tutto tranne gli anelli richiede cristalli che cadono orizzontali, qui supposti allineati al {alignment}%, poiché nessun rilevamento lo indica",skyOpticsHalo22:"un anello di {angle}°",skyOpticsHalo46:"un anello di {angle}°",skyOpticsParhelia:"pareli a {angle}° da entrambi i lati",skyOpticsTangentArc:"un arco tangente sopra",skyOpticsParhelicCircle:"un cerchio bianco che fa il giro del cielo alla sua stessa altezza",skyOpticsCircumzenithal:"un arco circumzenitale a {angle}° di altezza",skyOpticsCircumhorizontal:"un arco circumorizzontale molto più in basso",skyOpticsPillar:"una colonna eretta sopra",skyOpticsNoIce:"nessuna nube di ghiaccio: né alone né pareli",skyOpticsHidden:"nubi di ghiaccio in quota, ma uno strato più basso tra loro e l'osservatore",skyOpticsSun:"al Sole",skyOpticsMoon:"alla Luna",skyBowPossible:"pioggia e sole sufficienti per {forms}",skyBowMoon:"pioggia sotto una Luna illuminata al {lit}%, sufficiente per {forms} — un arcobaleno lunare, che l'occhio vede come un arco bianco",skyGlowBand:"la Via Lattea a {contrast}× il fondo del cielo, a {altitude}° di altezza {bearing}",skyGlowCone:"la luce zodiacale a {contrast}× il fondo del cielo, a {altitude}° di altezza {bearing}, a {elongation}° dal Sole — un tenue cono di luce inclinato, dai bordi sfumati, svanito entro un'ora",skyGlowZodiacalBand:"la banda zodiacale a {contrast}× il fondo del cielo, a {altitude}° di altezza {bearing} — tutta l'eclittica debolmente accesa, che non è ciò che la gente riferisce",skyGlowMoon:"né Via Lattea né luce zodiacale: una Luna illuminata al {lit}% teneva il cielo a {sky} magnitudini per secondo d'arco quadrato, dove ne servono 22",skyGlowTwilight:"né Via Lattea né luce zodiacale: il crepuscolo teneva ancora il cielo a {sky} magnitudini per secondo d'arco quadrato, dove ne servono 22",skyGlowTowns:"né Via Lattea né luce zodiacale: il bagliore delle città teneva il cielo a {sky} magnitudini per secondo d'arco quadrato, dove ne servono 22",skyGlowNothingUp:"cielo abbastanza buio ({sky} magnitudini per secondo d'arco quadrato), ma né il piano galattico né l'eclittica vi stavano abbastanza in alto",skyBowPrimary:"un arco di {radius}° di raggio, con la sommità a {top}° di altezza",skyBowSecondary:"un secondo, più tenue, a {radius}°, con i colori invertiti",skyBowSourceTooHigh:"pioggia, ma con l'astro a {altitude}° di altezza nessun arco poteva superare l'orizzonte: si trovano a {radius}° dal punto opposto",skyBowHidden:"pioggia, ma uno strato continuo tra essa e la luce: nessun arco",skyBowNoSource:"pioggia, e niente di illuminato per farne un arco",skySatellitesLit:"l'ombra della Terra era a {height} km sopra l'osservatore, quindi l'orbita bassa era ancora al sole — {count} oggetti catalogati erano in orbita quel mese",skySatellitesLitWith:"l'ombra della Terra era a {height} km sopra l'osservatore, quindi l'orbita bassa era ancora al sole — {count} oggetti catalogati erano in orbita quel mese, tra cui {eras}",skySatellitesShadowed:"l'ombra della Terra era a {height} km sopra l'osservatore: dei {count} oggetti catalogati in orbita quel mese, niente in orbita bassa era illuminato",skySatellitesNotYet:"non era ancora stato messo niente in orbita",skySatellitesDaylight:"tutto ciò che era in orbita era illuminato, come sempre di giorno, e {eras} potevano superare in luminosità persino questo cielo",skySatellitesDaylightOne:"tutto ciò che era in orbita era illuminato, come sempre di giorno, e {eras} poteva superare in luminosità persino questo cielo",skyUnknown:"non determinabile senza una data e un luogo",lookAtDecor:"Guardalo",addDecor:"Aggiungi",deleteDecor:"Elimina elemento della scenografia",undo:"Annulla",redo:"Ripristina",viewAccount:"Vedi il resoconto",noObserverRecording:"Nessun URL di registrazione per questo osservatore",masks:"Nasconde",masksNone:"Nessun fenomeno da nascondere per ora",masksBodyFully:"nascosto da questo oggetto",masksBodyPartly:"nascosto al {share} % da questo oggetto",masksBodyNot:"non nascosto da questo oggetto",modelPickerTitle:"Scegliere un modello 3D",modelPickerClose:"Chiudere",modelPickerChoose:"Scegliere un modello 3D",modelPickerUse:"Usa questo modello",modelPickerIncomplete:"Non disegnato finché non sono indicati il nome e la licenza del modello",addObserver:"Aggiungi osservatore",surveyLabel:"Scenografia ricavata da un rilievo",surveySource:"Scenografia da",surveyDated:"Rilevato il: {dates}.",surveyLaserLabel:"laser",surveyPhotoLabel:"foto aerea",surveyMapLabel:"carta",surveyLampsLabel:"OpenStreetMap",surveyWarning:"⚠ Questa scenografia viene da rilievi del {survey}, successivi all'osservazione ({observation}): non è ciò che c'era allora. Teneteli come riferimento, o eliminateli.",surveyRadius:"Raggio",surveyRadiusTitle:"Fino a dove intorno all'osservatore si interroga il rilievo, in metri. Un raggio più ampio porta edifici, ponti e linee più lontani; gli alberi vengono dal laser, che si interroga solo entro 150 m.",surveySourceTitle:"Il rilievo da cui sono ricavati, da soli, gli alberi, gli edifici, i ponti e le linee aeree attorno al luogo quando date un luogo alla registrazione: sono messi nell'elenco, al loro posto, con altezza e larghezza misurate. Le coordinate del luogo sono inviate a quel servizio. Nessuno lascia la scenografia a voi soli. Ciò che avete collocato voi non viene mai toccato.",surveySourceNone:"Nessuno (tutto a mano)",surveyBusy:"Ricerca della scenografia attorno all'osservatore…",surveyDone:"Da {source}: alberi {trees}, edifici {buildings}, ponti {bridges}, linee elettriche {lines}. Sono quelli del giorno del rilievo, non della registrazione: teneteli, spostateli o eliminateli.",surveyNone:"Nessun albero, edificio, ponte né linea elettrica trovato entro {radius} m.",surveyKept:"Ciò che avete collocato voi resta com'è.",surveyUnreachable:"Impossibile raggiungere il rilievo. Riprovate più tardi.",surveyFurniturePending:"Illuminazione pubblica e semafori: in attesa di OpenStreetMap…",surveyFurnitureDone:"Da {source}: lampioni {lamps}, semafori {signals}, attraversamenti {crossings}, segnali {signs}.",surveyFurnitureUnavailable:"Illuminazione pubblica e semafori non disponibili per ora: OpenStreetMap non risponde.",surveyFurnitureRetry:"Riprova",narrativePlaceholder:"Ciò che l'osservatore ha riferito, con parole sue",narrativeSource:"Redatto da",narrativeNeedsSetting:'Compila "{setting}" ({source}) per generare una ricostruzione dal resoconto',narrativeNeedsAsk:"Ancora niente da inviare",narrativeRemember:"Ricorda su questo dispositivo",narrativeDraft:"Genera ricostruzione",narrativeStop:"Ferma",narrativeWorking:"Lettura del resoconto…",narrativeApplied:"{count} campi scritti nell'editor",narrativeUnchanged:"Il resoconto non dice ancora nulla che la registrazione possa contenere",narrativeStated:"Ciò che l'osservatore ha detto",narrativeDerived:"Ricavato dal resoconto",narrativeAssumed:"Supposto, perché la ricostruzione funzioni — da verificare",narrativeGaps:"Ciò che niente ha potuto stabilire",narrativeErrorCredential:"Nessuna chiave, o una chiave rifiutata — controllala su console.anthropic.com",narrativeErrorRateLimited:"Troppe richieste sul tuo account: aspetta un momento e richiedi",narrativeErrorRefused:"Il resoconto non ha avuto risposta. Riformularlo può aiutare; richiederlo no",narrativeErrorMalformed:"La risposta non era una bozza utilizzabile — vale la pena richiederla ancora una volta",narrativeErrorUnreachable:"Nulla ha risposto: controlla la connessione",narrativeErrorRejected:"Rifiutato: {detail}",observerAge:"Età allora",observerBirth:"Nato il",observerPerception:{"color-vision":"Visione dei colori","color-vision.hint":"Come appaiono i colori a chi ha coni diversi (Machado et al. 2009). Ricolora soltanto: luminosità e risoluzione restano uguali.","color-vision.type":"Tipo","color-vision.type.normal":"Tipica","color-vision.type.protan":"Protan (rosso debole o cieco)","color-vision.type.deutan":"Deutan (verde debole o cieco)","color-vision.type.tritan":"Tritan (blu debole o cieco)","color-vision.severity":"Gravità",intoxication:"Alcol","intoxication.hint":"Riduce la sensibilità al contrasto di circa 0,9 dB a 0,08 % di alcol nel sangue (uno studio controllato; i risultati variano), mostrato fino a 0,1 % al massimo: un livello più alto viene registrato ma mostrato come 0,1 %, poiché oltre non è stato misurato nulla. Visione doppia, campo ristretto e altre droghe non sono modellati: nessuna fonte li quantifica.","intoxication.bloodAlcohol":"Alcolemia",fatigue:"Stanchezza","fatigue.hint":"Solo dichiarata: non è dimostrato che la mancanza di sonno cambi ciò che riceve un occhio sano, quindi l'immagine non cambia. Riguarda attenzione e memoria, non la vista.","fatigue.hoursAwake":"Sveglio da"},observerOccupation:"Professione",accountSource:"Resoconto raccolto",accountUrl:"Fonte (URL)",accountSourceUnknown:"sconosciuto",accountSourceOnSite:"indagine sul posto",accountSourceInterview:"colloquio di persona",accountSourceTelephone:"per telefono",accountSourceQuestionnaire:"questionario",accountSourceLetter:"l'ha scritto l'osservatore",accountSourceSocialMedia:"l'ha pubblicato l'osservatore in rete",accountSourcePress:"stampa o radiotelevisione",accountFollowedUp:"Ricontattato",accountUnknown:"sconosciuto",accountYes:"sì",accountNo:"no",questionUnanswered:"Nulla in questa registrazione risponde a una delle domande che una ricostruzione deve risolvere",durationRequired:"L'osservazione ha bisogno di una durata per poter essere riprodotta — indicala, o un'ora di fine, che può essere approssimativa",questionsUnanswered:"{count} delle domande a cui risponde una ricostruzione completa restano qui senza risposta",emptyDecor:"Nessun elemento della scenografia",emptyMilestones:"Nessun momento",emptyReferences:"Nessuna foto",emptyReferenceLandmarks:"Nessun punto di riferimento",emptyTraces:"Nessun tracciato dell'investigatore",emptyShapes:"Nessuna forma",addReference:"Aggiungi una foto",principalObserver:"Osservatore di questo resoconto",deleteObserver:"Elimina l'osservatore"};export{a as sightingEditorMessages_it};
@@ -1 +0,0 @@
1
- import{e as X,O as Q,f as Y,T as K,g as C,h as j,i as B}from"./rr0-sighting-editor.mjs";class I{constructor(t){this.survey=t}static CACHE_NAME="rr0-surroundings";static MAX_AGE_MS=720*3600*1e3;static FORMAT=7;static MAX_STORED=400;static asked=new Map;get id(){return this.survey.id}get name(){return this.survey.name}get attribution(){return this.survey.attribution}get creditUrl(){return this.survey.creditUrl}get contemporary(){return this.survey.contemporary}covers(t,e){return this.survey.covers(t,e)}async getSurroundings(t,e){const o=I.key(this.survey.id,t,e);let s=I.asked.get(o);return s===void 0&&(s=this.recalled(o,t,e),I.asked.set(o,s),s.catch(()=>I.asked.delete(o))),structuredClone(await s)}later(t,e){const o=this.survey.later?.(t,e);if(!o)return;const s=I.key(this.survey.id,t,e);return o.then(n=>{const a=I.partial.get(s);if(a){I.partial.delete(s);const{incomplete:r,...i}=a,h=[...a.credits??[],...n.credits??[]].filter((l,f,M)=>M.findIndex(d=>d.url===l.url)===f),c={...i,...n,dates:{...a.dates,...n.dates},...h.length>0?{credits:h}:{}};I.asked.set(s,Promise.resolve(c)),I.openCache().then(l=>l&&I.store(l,I.request(s),c))}return structuredClone(n)})}static partial=new Map;static forget(){I.partial.clear(),I.asked.clear()}static key(t,e,o){return`${t}/v${I.FORMAT}/${e.lat.toFixed(5)}/${e.lng.toFixed(5)}/${Math.round(o)}`}async recalled(t,e,o){const s=await I.openCache(),n=I.request(t);if(s)try{const r=await s.match(n);if(r){const{savedAt:i,surroundings:h}=await r.json();if(Date.now()-i<I.MAX_AGE_MS)return h;await s.delete(n)}}catch{}const a=await this.survey.getSurroundings(e,o);return a.incomplete?(I.asked.delete(t),I.partial.set(t,structuredClone(a)),a):(s&&I.store(s,n,a),a)}static async store(t,e,o){try{const s={savedAt:Date.now(),surroundings:o};await t.put(e,new Response(JSON.stringify(s),{headers:{"Content-Type":"application/json"}}));const n=await t.keys();for(const a of n.slice(0,Math.max(0,n.length-I.MAX_STORED)))await t.delete(a)}catch{}}static async openCache(){try{return typeof caches>"u"?void 0:await caches.open(I.CACHE_NAME)}catch{return}}static request(t){const e=typeof location>"u"?"http://localhost":location.origin;return new Request(`${e}/__surroundings__/${encodeURIComponent(t)}`)}}class tt{constructor(t){if(this.candidates=t,t.length===0)throw new Error("A survey needs at least one candidate");this.current=t[0]}current;get id(){return this.current.id}get name(){return this.current.name}get attribution(){return this.current.attribution}get creditUrl(){return this.current.creditUrl}get contemporary(){return this.current.contemporary}covers(t,e){return this.candidates.some(o=>o.covers(t,e))}async getSurroundings(t,e){let o;for(const s of this.candidates)if(s.covers(t.lat,t.lng))try{const n=await s.getSurroundings(t,e);return this.current=s,n}catch(n){if(o??=n,!(n instanceof X))throw n}throw o??new X("no-coverage","No survey reaches this place")}later(t,e){return this.current.later?.(t,e)}}class D{constructor(t,e,o,s){this.heights=t,this.building=e,this.width=o,this.height=s}static ROOF_PERCENTILE=.9;static STEP_M=.9;static RECTANGLE_FILL=.72;static MIN_DEPTH_M=2.5;static MAX_PARTS=24;static MAX_CELLS=640;buildings(t){const e=t.metresPerPixel,o=t.minAreaM2??12,s=new Uint8Array(this.width*this.height),n=[];for(let a=0;a<this.building.length;a++){if(!this.building[a]||s[a])continue;const r=this.patchFrom(a,s);if(!(r.length*e*e<o))for(const i of this.buildingsOf(r,e,o))Math.hypot(i.eastM,i.northM)<=t.radiusM&&n.push(i)}return n.sort((a,r)=>Math.hypot(a.eastM,a.northM)-Math.hypot(r.eastM,r.northM)),n.slice(0,t.maxBuildings??60)}patchFrom(t,e){const o=[],s=[t];for(e[t]=1;s.length>0;){const n=s.pop();o.push(n);const a=n%this.width,r=Math.floor(n/this.width);for(const[i,h]of[[1,0],[-1,0],[0,1],[0,-1]]){const c=a+i,l=r+h;if(c<0||l<0||c>=this.width||l>=this.height)continue;const f=l*this.width+c;this.building[f]&&!e[f]&&Math.abs(this.heights[f]-this.heights[n])<=D.STEP_M&&(e[f]=1,s.push(f))}}return o}buildingsOf(t,e,o){const s=this.width/2,n=this.height/2,a=[],r=[],i=[];for(const h of t){const c=h%this.width,l=Math.floor(h/this.width);a.push((c+.5-s)*e),r.push((n-l-.5)*e),i.push(this.heights[h])}return D.ofPoints(a,r,i,e,o)}static ofPoints(t,e,o,s,n,a=D.RECTANGLE_FILL,r=[]){const i=[];for(let E=0;E<t.length;E++)for(const[p,N]of[[-.5,-.5],[.5,-.5],[-.5,.5],[.5,.5]])i.push([t[E]+p*s,e[E]+N*s]);const h=D.hull(i),{angle:c,rectangle:l}=D.smallestRectangle(h),f=t.length*s*s,M=(l.maxU-l.minU)*(l.maxV-l.minV);if(f/M>=a||f<4*n)return[D.building(l,c,D.roof(o))];const d=h.map((E,p)=>({from:{east:E[0],north:E[1]},to:{east:h[(p+1)%h.length][0],north:h[(p+1)%h.length][1]}})),g=D.dominantAngles([...r,...d]);return D.parts(t,e,o,g.length>0?g:[c],s,n)}static dominantAngles(t,e=3){const o=new Map;for(const s of t){const n=Math.hypot(s.to.east-s.from.east,s.to.north-s.from.north);if(n<1e-6)continue;const a=(Math.atan2(s.to.north-s.from.north,s.to.east-s.from.east)%(Math.PI/2)+Math.PI/2)%(Math.PI/2),r=Math.round(a/(Math.PI/60));o.set(r,(o.get(r)??0)+n)}return[...o.entries()].sort((s,n)=>n[1]-s[1]).slice(0,e).map(([s])=>s*Math.PI/60)}static parts(t,e,o,s,n,a){let r=t.map((h,c)=>c);const i=[];for(let h=0;h<D.MAX_PARTS&&r.length>0;h++){let c;for(const M of s){const d=D.largestIn(t,e,r,M,n);d&&(c===void 0||d.area>c.area)&&(c=d)}if(c===void 0||c.area<a)break;const l=c.covered;Math.min(c.rectangle.maxU-c.rectangle.minU,c.rectangle.maxV-c.rectangle.minV)>=D.MIN_DEPTH_M&&i.push(D.building(c.rectangle,c.angle,D.roof([...l].map(M=>o[M])))),r=r.filter(M=>!l.has(M))}return i}static largestIn(t,e,o,s,n){const a=Math.cos(s),r=Math.sin(s);let i=1/0,h=-1/0,c=1/0,l=-1/0;const f=[],M=[];for(const A of o){const w=t[A]*a+e[A]*r,v=-t[A]*r+e[A]*a;f.push(w),M.push(v),i=Math.min(i,w),h=Math.max(h,w),c=Math.min(c,v),l=Math.max(l,v)}const d=Math.max(n*Math.SQRT2,Math.max(h-i,l-c)/D.MAX_CELLS),g=Math.max(1,Math.ceil((h-i)/d+1e-9)),E=Math.max(1,Math.ceil((l-c)/d+1e-9)),p=new Uint8Array(g*E),N=o.map((A,w)=>{const v=Math.min(g-1,Math.max(0,Math.floor((f[w]-i)/d))),x=Math.min(E-1,Math.max(0,Math.floor((M[w]-c)/d)));return p[x*g+v]=1,x*g+v}),y=D.largestRectangle(p,g,E);if(y===void 0)return;const m=new Set;return o.forEach((A,w)=>{const v=N[w]%g,x=Math.floor(N[w]/g);v>=y.column&&v<y.column+y.columns&&x>=y.row&&x<y.row+y.rows&&m.add(A)}),{area:y.area*d*d,angle:s,covered:m,rectangle:{minU:i+y.column*d,maxU:i+(y.column+y.columns)*d,minV:c+y.row*d,maxV:c+(y.row+y.rows)*d}}}static largestRectangle(t,e,o){const s=new Array(e).fill(0);let n;for(let a=0;a<o;a++){for(let i=0;i<e;i++)s[i]=t[a*e+i]?s[i]+1:0;const r=[];for(let i=0;i<=e;i++){const h=i===e?0:s[i];for(;r.length>0&&s[r[r.length-1]]>=h;){const c=r.pop(),l=r.length===0?i:i-r[r.length-1]-1,f=s[c]*l;(n===void 0||f>n.area)&&(n={column:i-l,row:a-s[c]+1,columns:l,rows:s[c],area:f})}r.push(i)}}return n}static roof(t){const e=[...t].sort((o,s)=>o-s);return Math.max(2,e[Math.min(e.length-1,Math.floor(e.length*D.ROOF_PERCENTILE))])}static building(t,e,o){const s=Math.cos(e),n=Math.sin(e),a=t.maxU-t.minU,r=t.maxV-t.minV,i=(t.minU+t.maxU)/2,h=(t.minV+t.maxV)/2,l=((90-(a<r?e:e+Math.PI/2)*180/Math.PI)%180+180)%180;return{eastM:D.tenth(i*s-h*n),northM:D.tenth(i*n+h*s),widthM:D.tenth(Math.max(a,r)),lengthM:D.tenth(Math.min(a,r)),heightM:D.tenth(o),headingDeg:Math.round(l*10)/10}}static smallestRectangle(t){let e={area:1/0,angle:0,rectangle:{minU:0,maxU:0,minV:0,maxV:0}};for(let o=0;o<Math.max(1,t.length);o++){const[s,n]=t[o]??[0,0],[a,r]=t[(o+1)%t.length]??[1,0],i=Math.atan2(r-n,a-s),h=Math.cos(i),c=Math.sin(i);let l=1/0,f=-1/0,M=1/0,d=-1/0;for(const[E,p]of t){const N=E*h+p*c,y=-E*c+p*h;l=Math.min(l,N),f=Math.max(f,N),M=Math.min(M,y),d=Math.max(d,y)}const g=(f-l)*(d-M);g<e.area&&(e={area:g,angle:i,rectangle:{minU:l,maxU:f,minV:M,maxV:d}})}return e}static hull(t){const e=[...t].sort((r,i)=>r[0]-i[0]||r[1]-i[1]),o=e.filter((r,i)=>i===0||r[0]!==e[i-1][0]||r[1]!==e[i-1][1]);if(o.length<3)return o;const s=(r,i,h)=>(i[0]-r[0])*(h[1]-r[1])-(i[1]-r[1])*(h[0]-r[0]),n=[];for(const r of o){for(;n.length>=2&&s(n[n.length-2],n[n.length-1],r)<=0;)n.pop();n.push(r)}const a=[];for(const r of[...o].reverse()){for(;a.length>=2&&s(a[a.length-2],a[a.length-1],r)<=0;)a.pop();a.push(r)}return[...n.slice(0,-1),...a.slice(0,-1)]}static tenth(t){return Math.round(t*10)/10}}class k{constructor(t,e,o,s){this.heights=t,this.vegetation=e,this.width=o,this.height=s}static SUMMIT_RADIUS_M=2.5;static CROWN_REACH_M=8;static MAX_WIDTH_M=16;static MIN_WIDTH_M=2;static tenth(t){return Math.round(t*10)/10}trees(t){const e=t.metresPerPixel,o=t.minHeightM??4,s=t.eyeM??1.6,n=t.minElevationDeg??2,a=Math.max(1,Math.round(k.SUMMIT_RADIUS_M/e)),r=Math.round(k.CROWN_REACH_M/e),i=this.width/2,h=this.height/2,c=[];for(let l=0;l<this.height;l++)for(let f=0;f<this.width;f++){const M=this.canopy(f,l);if(M<o)continue;const d=(f+.5-i)*e,g=(h-l-.5)*e,E=Math.hypot(d,g);if(E>t.radiusM||!this.isSummit(f,l,M,a))continue;const p=Math.atan2(M-s,Math.max(E,1))*180/Math.PI;p<n||c.push({tree:{eastM:k.tenth(d),northM:k.tenth(g),heightM:k.tenth(M),widthM:k.tenth(this.crownWidth(f,l,M,e,r))},elevation:p})}return c.sort((l,f)=>f.elevation-l.elevation),c.slice(0,t.maxTrees??150).map(l=>l.tree)}canopy(t,e){if(t<0||e<0||t>=this.width||e>=this.height)return 0;const o=e*this.width+t;return this.vegetation[o]?this.heights[o]:0}isSummit(t,e,o,s){for(let n=-s;n<=s;n++)for(let a=-s;a<=s;a++){if(a===0&&n===0)continue;const r=this.canopy(t+a,e+n);if(r>o||r===o&&(n<0||n===0&&a<0))return!1}return!0}crownWidth(t,e,o,s,n){let a=0;for(let i=-n;i<=n;i++)for(let h=-n;h<=n;h++)Math.hypot(h,i)*s<=k.CROWN_REACH_M&&this.canopy(t+h,e+i)>=o*.5&&a++;const r=2*Math.sqrt(a*s*s/Math.PI);return Math.max(k.MIN_WIDTH_M,Math.min(r,k.MAX_WIDTH_M))}}class T{static WALLS={1:"stone",2:"meuliere",3:"concrete",4:"brick",5:"block",6:"wood",9:"other"};static ROOFS={1:"tile",2:"slate",3:"zinc",4:"concrete",9:"other"};static WALL_COLOURS={stone:"#b9ae9b",meuliere:"#b8a78a",concrete:"#b4b2ac",brick:"#a65f48",block:"#d0c6b2",wood:"#7d5c3e",other:"#c9c0ae"};static PLASTER="#d3cab8";static ROOF_COLOURS={tile:"#a0583f",slate:"#4a5059",zinc:"#8d969c",concrete:"#8f8e8a",other:"#7a7872"};static VARIATION=.12;static OLD_ROOF="#7d858c";static OLD_STOREY_M=3.6;static GRAND_STOREY_M=4.5;static MIN_STOREY_M=2.4;static MAX_STOREY_M=6;static of(t,e){const o=String(t??"").trim();if(!/^\d{1,2}$/.test(o))return;const s=Number(o),n=s%10!==0?s%10:Math.floor(s/10);return(e==="wall"?T.WALLS:T.ROOFS)[String(n)]}static roofColor(t){return t?T.ROOF_COLOURS[t]:void 0}static fit(t){return t.map(e=>{const o=e.style,s={...e.facade,color:e.facade?.color??T.wallColor(e)};o==="church"?s.openings="lancet":o==="monument"?s.plain=!0:(o==="old"||o==="grand")&&(s.openings="tall");const n=T.storeyOf(e);n!==void 0&&o!=="church"&&o!=="monument"&&(s.storeyM=n);const a=o==="old"&&e.roof?.color===void 0?{shape:"flat",riseM:0,...e.roof,color:T.OLD_ROOF}:e.roof;return{...e,facade:s,...a?{roof:a}:{}}})}static storeyOf(t){const e=t.heightM-(t.roof?.riseM??0);if(t.floors&&t.floors>0){const o=e/t.floors;if(o>=T.MIN_STOREY_M&&o<=T.MAX_STOREY_M)return Math.round(o*100)/100}return t.style==="old"?T.OLD_STOREY_M:t.style==="grand"?T.GRAND_STOREY_M:void 0}static wallColor(t){const e=t.style==="church"||t.style==="monument"||t.style==="old",o=t.wallMaterial?T.WALL_COLOURS[t.wallMaterial]:e?T.WALL_COLOURS.stone:T.PLASTER,s=Math.sin(t.eastM*12.9898+t.northM*78.233)*43758.5453,n=1+(s-Math.floor(s)-.5)*2*T.VARIATION,a=r=>Math.max(0,Math.min(255,Math.round(parseInt(o.slice(r,r+2),16)*n))).toString(16).padStart(2,"0");return`#${a(1)}${a(3)}${a(5)}`}}class R{static MIN_RISE_M=1.2;static MIN_EAVES_M=2.5;static MIN_SEEN=.35;static NO_DATA=-9999;static BANDS=7;static INSET_M=.9;static LIFT=1.18;static PEAK=.3;static LEVEL=.45;static fit(t,e,o){return!e&&!o&&!t.some(s=>s.roofMaterial)?t:t.map(s=>{const n=e?R.shapeOf(s,e):void 0,a=(o?R.colorOf(s,o):void 0)??T.roofColor(s.roofMaterial);if(!n&&!a)return s;const r={shape:n?.shape??"flat",...n?.ridge==="depth"?{ridge:"depth"}:{},riseM:n?.riseM??0,...a?{color:a}:{}},i=n&&n.shape!=="flat"?n.topM:s.heightM;return{...s,heightM:i,roof:r}})}static world(t,e,o){const s=t.headingDeg*Math.PI/180;return{east:t.eastM+e*Math.cos(s)+o*Math.sin(s),north:t.northM-e*Math.sin(s)+o*Math.cos(s)}}static shapeOf(t,e){const o=R.BANDS,s=Math.max(e.metresPerPixel,.5),n=t.widthM/2-R.INSET_M,a=t.lengthM/2-R.INSET_M;if(n<=0||a<=0)return;const r=[],i=Array.from({length:o},()=>({sum:0,n:0})),h=Array.from({length:o},()=>({sum:0,n:0}));let c=0;for(let w=-n;w<=n;w+=s)for(let v=-a;v<=a;v+=s){c++;const{east:x,north:$}=R.world(t,w,v),V=Math.floor(x/e.metresPerPixel+e.size/2),z=Math.floor(e.size/2-$/e.metresPerPixel);if(V<0||z<0||V>=e.size||z>=e.size)continue;const H=z*e.size+V,P=e.heights[H];if(e.vegetation[H]||P===R.NO_DATA||!(P>0))continue;r.push(P);const Z=i[Math.min(o-1,Math.floor((w+n)/(2*n)*o))],J=h[Math.min(o-1,Math.floor((v+a)/(2*a)*o))];Z.sum+=P,Z.n++,J.sum+=P,J.n++}if(c===0||r.length/c<R.MIN_SEEN)return;r.sort((w,v)=>w-v);const l=R.percentile(r,.08),f=R.percentile(r,.92),M=f-l;if(l<R.MIN_EAVES_M||M>Math.min(t.widthM,t.lengthM))return;if(M<R.MIN_RISE_M)return{shape:"flat",riseM:0,topM:f};const d=R.profile(i),g=R.profile(h);if(!d||!g)return;const E=R.peak(g)/M,p=R.peak(d)/M,N=R.spread(d)/M,y=R.spread(g)/M,m=E>=R.PEAK&&N<=R.LEVEL,A=p>=R.PEAK&&y<=R.LEVEL;if(m&&(!A||E>=p))return{shape:"gable",ridge:"width",riseM:M,topM:f};if(A)return{shape:"gable",ridge:"depth",riseM:M,topM:f};if(E>=R.PEAK&&p>=R.PEAK/2)return{shape:"hip",ridge:"width",riseM:M,topM:f}}static profile(t){const e=t.map(o=>o.n>0?o.sum/o.n:NaN);return e.filter(Number.isFinite).length>=t.length-1?e.map((o,s)=>Number.isFinite(o)?o:R.neighbour(e,s)):void 0}static neighbour(t,e){return Number.isFinite(t[e-1])?t[e-1]:t[e+1]}static peak(t){const e=Math.max(1,Math.floor(t.length/3)),o=n=>n.reduce((a,r)=>a+r,0)/n.length,s=[...t.slice(0,e),...t.slice(t.length-e)];return o(t.slice(e,t.length-e))-o(s)}static spread(t){return Math.max(...t)-Math.min(...t)}static percentile(t,e){return t[Math.min(t.length-1,Math.floor(t.length*e))]}static colorOf(t,e){const o=Math.max(e.metresPerPixel,.5),s=Math.max(t.widthM/2-R.INSET_M,o),n=Math.max(t.lengthM/2-R.INSET_M,o),a=[],r=[],i=[];for(let l=-s;l<=s;l+=o)for(let f=-n;f<=n;f+=o){const{east:M,north:d}=R.world(t,l,f),g=Math.floor(M/e.metresPerPixel+e.size/2),E=Math.floor(e.size/2-d/e.metresPerPixel);if(g<0||E<0||g>=e.size||E>=e.size)continue;const p=(E*e.size+g)*e.samples,N=e.values[p],y=e.values[p+1],m=e.values[p+2];y>N&&y>m||(a.push(N),r.push(y),i.push(m))}if(a.length===0)return;const h=l=>l.sort((f,M)=>f-M)[Math.floor(l.length/2)],c=l=>Math.min(255,Math.round(l*R.LIFT)).toString(16).padStart(2,"0");return`#${c(h(a))}${c(h(r))}${c(h(i))}`}}class G{static DEFAULT_HEIGHT_M=6;static METRES_PER_DEGREE=111320;static STREET_SPACING_M=35;static KERB_OFFSET_M=1;static DEFAULT_WIDTH_M=5.5;static PATIENCE_MS=15e3;static MAX=150;static lampsFrom(t,e,o){const s=[],n=new Set;for(const r of t.elements??[]){if(r.id!==void 0){const l=`${r.type}/${r.id}`;if(n.has(l))continue;n.add(l)}if(r.type==="way"){r.tags?.lit==="yes"&&G.alongStreet(r,e,s);continue}if(r.tags?.highway!=="street_lamp"||typeof r.lat!="number"||typeof r.lon!="number")continue;const i=(r.lon-e.lng)*G.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180),h=(r.lat-e.lat)*G.METRES_PER_DEGREE;if(Math.hypot(i,h)>o)continue;const c=Number.parseFloat(r.tags?.height??"");s.push({eastM:Math.round(i*10)/10,northM:Math.round(h*10)/10,...Number.isFinite(c)&&c>=2&&c<=20?{heightM:c}:{}})}const a=s.filter(r=>Math.hypot(r.eastM,r.northM)<=o);return s.length=0,s.push(...a),s.sort((r,i)=>Math.hypot(r.eastM,r.northM)-Math.hypot(i.eastM,i.northM)),s.slice(0,G.MAX)}static alongStreet(t,e,o){const s=t.geometry;if(!s||s.length<2)return;const n=d=>[(d.lon-e.lng)*G.METRES_PER_DEGREE*Math.cos(e.lat*Math.PI/180),(d.lat-e.lat)*G.METRES_PER_DEGREE],a=s.map(n),r=Number.parseFloat(t.tags?.width??""),i=Number.parseInt(t.tags?.lanes??"",10),c=(Number.isFinite(r)&&r>0?r:Number.isFinite(i)&&i>0?i*3.5:G.DEFAULT_WIDTH_M)/2+G.KERB_OFFSET_M;let l=1,f=G.STREET_SPACING_M/2,M=0;for(let d=1;d<a.length;d++){const[g,E]=a[d-1],[p,N]=a[d],y=Math.hypot(p-g,N-E);if(y===0)continue;const m=(p-g)/y,A=(N-E)/y;for(;f<=M+y;f+=G.STREET_SPACING_M){const w=f-M;o.push({eastM:Math.round((g+m*w+A*c*l)*10)/10,northM:Math.round((E+A*w-m*c*l)*10)/10}),l=-l}M+=y}}}class u{constructor(t={},e=[],o=[]){this.lampSources=e,this.signalSources=o,this.client=new Q(t)}static METRES_PER_DEGREE=111320;static KERB_OFFSET_M=.6;static SETBACK_M=.5;static MIN_CROSSING_M=3;static MAX_CROSSING_M=30;static SAME_CROSSING_M=5;static SAME_HEAD_M=2.5;static SAME_HEAD_DEG=45;static MAX_SIGNALS=160;static MAX_CROSSINGS=150;static MAX_SIGNS=100;static ROADS=new Set([...Y.DRIVABLE,"living_street","busway","road"]);static ON_ROAD="^(traffic_signals|crossing|stop|give_way)$";static CREDIT={name:"OpenStreetMap",url:"https://www.openstreetmap.org/copyright",licence:"ODbL"};client;local(t,e){const o=u.boxOf(t,e),s=(r,i)=>{if(!r)return Promise.resolve(void 0);const h=`${r.credit.url} ${o}`;let c=u.localPending.get(h);return c||(c=i().then(l=>({credit:r.credit,found:l}),()=>{u.localPending.delete(h)}),u.localPending.set(h,c)),c},n=this.lampSources.find(r=>r.covers(t.lat,t.lng)),a=this.signalSources.find(r=>r.covers(t.lat,t.lng));return Promise.all([s(n,()=>n.lampsNear(t,e)),s(a,()=>a.signalsNear(t,e))]).then(([r,i])=>({lamps:r,signals:i}))}static localPending=new Map;static withLocal(t,e){const o=e?.lamps?e.lamps.found:t.lamps,s=e?.signals?e.signals.found:t.signals,a=[...u.found({crossings:t.crossings,signs:t.signs,...e?.lamps?{}:{lamps:o},...e?.signals?{}:{signals:s}})?[u.CREDIT]:[],...e?.lamps&&e.lamps.found.length>0?[e.lamps.credit]:[],...e?.signals&&e.signals.found.length>0?[e.signals.credit]:[]],{lamps:r,signals:i,credits:h,...c}=t;return{...c,...o?.length?{lamps:o}:{},...s?.length?{signals:s}:{},...a.length>0?{credits:a}:{}}}static today(){return new Date().toISOString().slice(0,10)}static later(t,e,o){return t?.answered(e,o).then(s=>({...s,...u.found(s)?{dates:{lamps:u.today()}}:{}}))}static found(t){return!!(t?.lamps?.length||t?.signals?.length||t?.crossings?.length||t?.signs?.length)}static query(t){const e=u.ON_ROAD;return`[out:json][timeout:25];(node["highway"="street_lamp"](${t});way["highway"]["lit"="yes"](${t});node["highway"~"${e}"](${t});node["traffic_sign"](${t});way["footway"="crossing"](${t}););out geom;(node._["highway"~"${e}"];node._["traffic_sign"];)->.kerb;way(bn.kerb)["highway"];out geom;`}static pending=new Map;async near(t,e){const o=this.ask(u.boxOf(t,e)),s=this.local(t,e);let n;const a=Symbol("late"),r=new Promise(i=>{n=setTimeout(()=>i(a),G.PATIENCE_MS)});try{const[i,h]=await Promise.all([Promise.race([o,r]),Promise.race([s,r])]),c=h===a?void 0:h;return i===a||i===void 0?{...u.withLocal({},c),incomplete:!0}:u.withLocal(u.from(i,t,e),c)}finally{clearTimeout(n)}}static RETRY_DELAYS_MS=[15e3,6e4,18e4,6e5];async answered(t,e){const o=u.boxOf(t,e);for(let s=0;;s++){const n=await this.ask(o);if(n)return u.withLocal(u.from(n,t,e),await this.local(t,e));if(s>=u.RETRY_DELAYS_MS.length)throw new Error("Overpass did not answer");await new Promise(a=>setTimeout(a,u.RETRY_DELAYS_MS[s]))}}ask(t){let e=u.pending.get(t);return e||(e=this.client.query(u.query(t)).catch(()=>{u.pending.delete(t)}),u.pending.set(t,e)),e}static boxOf(t,e){const o=e/u.METRES_PER_DEGREE,s=e/(u.METRES_PER_DEGREE*Math.cos(t.lat*Math.PI/180));return[t.lat-o,t.lng-s,t.lat+o,t.lng+s].map(n=>n.toFixed(6)).join(",")}static forget(){u.pending.clear(),u.localPending.clear()}static from(t,e,o){const s=G.lampsFrom(t,e,o),n=Math.cos(e.lat*Math.PI/180),a=(m,A)=>[(A-e.lng)*u.METRES_PER_DEGREE*n,(m-e.lat)*u.METRES_PER_DEGREE],r=(m,A)=>`${m.toFixed(7)},${A.toFixed(7)}`,i=new Map,h=new Set,c=[],l=[];for(const m of t.elements??[]){if(m.type==="node"){typeof m.lat=="number"&&typeof m.lon=="number"&&l.push(m);continue}if(m.type!=="way"||!m.geometry||m.geometry.length<2)continue;if(m.id!==void 0){if(h.has(m.id))continue;h.add(m.id)}const A=m.tags??{};if(A.footway==="crossing"&&c.push(m),!u.ROADS.has(A.highway??""))continue;const w=m.geometry.map(v=>a(v.lat,v.lon));m.geometry.forEach((v,x)=>{const $=r(v.lat,v.lon);i.set($,[...i.get($)??[],{way:m,points:w,index:x}])})}const f=[],M=[],d=[],g=new Set;for(const m of l){if(m.id!==void 0){if(g.has(m.id))continue;g.add(m.id)}const A=m.tags??{},w=a(m.lat,m.lon),v=i.get(r(m.lat,m.lon))??[],x=A.highway;if(x==="traffic_signals")for(const H of u.approaches(v,u.directionOf(A),!1))f.push(u.head(w,H,"vehicles"));if(x==="crossing"||x==="traffic_signals"&&A.crossing!==void 0){const H=v[0];if(H&&u.marked(A)){const P=u.directionAt(H);P&&M.push({eastM:u.round(w[0]),northM:u.round(w[1]),headingDeg:u.heading(P),widthM:Y.widthOf(H.way.tags??{})}),P&&(A.crossing==="traffic_signals"||A["crossing:signals"]==="yes")&&f.push(...u.pedestrianHeads(w,P,H))}}if(x==="traffic_signals")continue;const $=x==="stop"?{face:"stop"}:x==="give_way"?{face:"give-way"}:u.faceOf(A);if(!$)continue;const V=A.traffic_sign?{code:A.traffic_sign}:{};if(v.length>0){const H=u.approaches(v,u.directionOf(A),!0)[0];if(H){const P=u.head(w,H,"vehicles");d.push({eastM:P.eastM,northM:P.northM,headingDeg:P.headingDeg,...$,...V})}continue}const z=u.compassOf(A.direction);z!==void 0&&d.push({eastM:u.round(w[0]),northM:u.round(w[1]),headingDeg:(z+180)%360,...$,...V})}for(const m of c){const A=u.crossingAlong(m,a);A&&!M.some(w=>Math.hypot(w.eastM-A.eastM,w.northM-A.northM)<u.SAME_CROSSING_M)&&M.push(A)}const E=f.filter((m,A)=>!f.slice(0,A).some(w=>w.for===m.for&&Math.hypot(w.eastM-m.eastM,w.northM-m.northM)<u.SAME_HEAD_M&&Math.abs((w.headingDeg-m.headingDeg+540)%360-180)<u.SAME_HEAD_DEG)),p=(m,A)=>m.filter(w=>Math.hypot(w.eastM,w.northM)<=o).sort((w,v)=>Math.hypot(w.eastM,w.northM)-Math.hypot(v.eastM,v.northM)).slice(0,A),N={};s.length>0&&(N.lamps=s);const y={signals:p(E,u.MAX_SIGNALS),crossings:p(M,u.MAX_CROSSINGS),signs:p(d,u.MAX_SIGNS)};return y.signals.length>0&&(N.signals=y.signals),y.crossings.length>0&&(N.crossings=y.crossings),y.signs.length>0&&(N.signs=y.signs),N}static approaches(t,e,o){const s=[];for(const a of t){const r=a.way.tags??{},i=r.oneway==="yes"||r.oneway==="true"||r.oneway==="1"||r.junction==="roundabout"||r.highway==="motorway",h=r.oneway==="-1",{points:c,index:l}=a,f=(d,g)=>{let E=0;for(let p=Math.min(d,g);p<Math.max(d,g);p++)E+=Math.hypot(c[p+1][0]-c[p][0],c[p+1][1]-c[p][1]);return E},M=d=>{const g=c[l][0]-c[d][0],E=c[l][1]-c[d][1],p=Math.hypot(g,E);return p>0?[g/p,E/p]:void 0};if(l>0&&!h){const d=M(l-1);d&&s.push({approach:{unit:d,road:a},toEndM:f(l,c.length-1),forward:!0})}if(l<c.length-1&&!i){const d=M(l+1);d&&s.push({approach:{unit:d,road:a},toEndM:f(0,l),forward:!1})}}const n=e!==void 0&&t.length===1?s.filter(a=>a.forward===(e==="forward")):s;return!o||n.length<=1?n.map(a=>a.approach):[n.reduce((a,r)=>r.toEndM<a.toEndM?r:a).approach]}static head(t,e,o){const[s,n]=e.unit,a=Y.widthOf(e.road.way.tags??{})/2+u.KERB_OFFSET_M,r=u.SETBACK_M,i=u.heading(e.unit);return{eastM:u.round(t[0]-s*r+n*a),northM:u.round(t[1]-n*r-s*a),headingDeg:(i+180)%360,for:o,phase:K.phaseOf(i)}}static pedestrianHeads(t,e,o){const s=Y.widthOf(o.way.tags??{})/2+u.KERB_OFFSET_M,n=u.heading(e),a=K.phaseOf(n);return[1,-1].map(r=>({eastM:u.round(t[0]+e[1]*s*r),northM:u.round(t[1]-e[0]*s*r),headingDeg:(n+(r===1?270:90))%360,for:"pedestrians",phase:a}))}static crossingAlong(t,e){if(!u.marked(t.tags??{}))return;const o=t.geometry.map(h=>e(h.lat,h.lon)),[s,n]=o[0],[a,r]=o[o.length-1],i=Math.hypot(a-s,r-n);if(!(i<u.MIN_CROSSING_M))return{eastM:u.round((s+a)/2),northM:u.round((n+r)/2),headingDeg:(u.heading([(a-s)/i,(r-n)/i])+90)%360,widthM:Math.round(Math.min(i,u.MAX_CROSSING_M)*10)/10}}static marked(t){const e=t.crossing;return e!=="unmarked"&&e!=="no"&&e!=="informal"&&t["crossing:markings"]!=="no"}static directionAt(t){const{points:e,index:o}=t,[s,n]=o<e.length-1?[e[o],e[o+1]]:[e[o-1],e[o]],a=Math.hypot(n[0]-s[0],n[1]-s[1]);return a>0?[(n[0]-s[0])/a,(n[1]-s[1])/a]:void 0}static directionOf(t){const e=t["traffic_signals:direction"]??t["traffic_sign:direction"]??t.direction;return e==="forward"||e==="backward"?e:void 0}static compassOf(t){if(t===void 0)return;const e=Number.parseFloat(t);if(Number.isFinite(e)&&/^\s*-?\d/.test(t))return(e%360+360)%360;const s=["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"].indexOf(t.trim().toUpperCase());return s<0?void 0:s*22.5}static faceOf(t){const e=t.traffic_sign;if(!e||e==="no"||e==="none")return;const o=e.split(/[;,]/).map(s=>s.trim());if(o.some(s=>/stop|:AB4\b|:206\b|:R1-1\b|:B2\b/i.test(s)))return{face:"stop"};if(o.some(s=>/give_way|yield|:AB3a\b|:205\b|:R1-2\b|:B1\b/i.test(s)))return{face:"give-way"};for(const s of o){const n=/maxspeed|:B14\b|:274\b|:C14\b|:R2-1\b/i.test(s)?Number.parseInt(/\[(\d+)\]/.exec(s)?.[1]??t.maxspeed??"",10):Number.NaN;if(Number.isFinite(n)&&n>0)return{face:"speed-limit",value:n}}return{face:"other"}}static heading([t,e]){return Math.round((Math.atan2(t,e)*180/Math.PI+360)%360*10)/10}static round(t){return Math.round(t*10)/10}}class et{id="ign-lidar-hd";name="IGN LiDAR HD";attribution="Canopy and roofs © IGN, LiDAR HD (Licence Ouverte 2.0), as surveyed on a day the service does not give";creditUrl="https://geoservices.ign.fr/lidarhd";contemporary=!0;platform;furniture;constructor(t={},e){this.platform=new C(t),this.furniture=e}covers(t,e){return C.covers(t,e)}later(t,e){return u.later(this.furniture,t,e)}async getSurroundings(t,e){if(!this.covers(t.lat,t.lng))throw new X("no-coverage","The LiDAR HD survey covers France only");const o=C.lidarRadius(e),[s,n,a,r,i]=await Promise.all([this.platform.lidar(t,o),this.platform.photo(t,o).catch(()=>{}),this.furniture?.near(t,e),this.platform.laserDate(t),this.platform.photoDate(t)]);return{trees:new k(s.heights,s.vegetation,s.size,s.size).trees({metresPerPixel:s.metresPerPixel,radiusM:o}),buildings:T.fit(R.fit(new D(s.heights,s.building,s.size,s.size).buildings({metresPerPixel:s.metresPerPixel,radiusM:o,maxBuildings:300}),s,n)),bridges:[],lines:[],...a,dates:{...r?{laser:r}:{},...n&&i?{photo:i}:{},...u.found(a)?{lamps:u.today()}:{}}}}}class O{static MAP_NATURES={Eglise:"church",Chapelle:"church",Monument:"monument","Tour, donjon":"monument","Fort, blockhaus, casemate":"monument","Arc de triomphe":"monument","Arène ou théâtre antique":"monument",Château:"old"};static OSM_BUILDINGS={cathedral:"church",church:"church",chapel:"church",basilica:"church",temple:"church",mosque:"church",synagogue:"church",shrine:"church",religious:"church",castle:"old",palace:"old",fortress:"monument",bunker:"monument",triumphal_arch:"monument"};static OSM_HISTORIC={church:"church",chapel:"church",monastery:"old",castle:"old",manor:"old",fort:"monument",tower:"monument",monument:"monument",memorial:"monument",city_gate:"monument"};static OLD_BEFORE=1900;static GRAND_FROM_M=15;static GRAND_UP_TO_M=40;static TOWER_SLENDERNESS=2;static CHURCH_PITCH=.7;static CHURCH_ROOF_OF_WALLS=.35;static CHURCH_ROOF_COLOUR="#5a6068";static ofMap(t){const e=O.year(t.date_d_apparition),s=O.MAP_NATURES[String(t.nature??"")]??(t.usage_1==="Religieux"?"church":void 0)??O.ofYear(e)??O.grand(t);return{...s?{style:s}:{},...e!==void 0?{builtYear:e}:{}}}static ofOsm(t){const e=O.year(t.start_date),o=t.historic&&t.historic!=="no"?O.OSM_HISTORIC[t.historic]??"old":void 0,s=t.amenity==="place_of_worship"?"church":void 0,n=O.OSM_BUILDINGS[t.building??""]??o??s??O.ofYear(e);return{...n?{style:n}:{},...e!==void 0?{builtYear:e}:{}}}static year(t){const e=Number(/\b(\d{4})\b/.exec(String(t??""))?.[1]);return Number.isFinite(e)&&e>=1e3&&e<=2100?e:void 0}static fit(t){return t.map(e=>e.style==="church"?O.church(e):e)}static isTower(t){return t.heightM>=O.TOWER_SLENDERNESS*Math.max(t.widthM,t.lengthM)}static church(t){const e=t.roof?.color??O.CHURCH_ROOF_COLOUR;if(O.isTower(t))return{...t,roof:{shape:"flat",riseM:0,color:e}};if(t.roof&&t.roof.shape!=="flat")return t;const o=Math.round(Math.min(O.CHURCH_PITCH*t.lengthM,O.CHURCH_ROOF_OF_WALLS*t.heightM)*10)/10,s={shape:"gable",riseM:o,color:e};return{...t,heightM:Math.round((t.heightM+o)*10)/10,roof:s}}static ofYear(t){return t!==void 0&&t<O.OLD_BEFORE?"old":void 0}static grand(t){const e=Number(t.hauteur),o=Number(t.nombre_d_etages);if(!(Number.isFinite(o)&&o>0)&&!(t.usage_1==="Résidentiel"||t.date_d_apparition))return e>=O.GRAND_FROM_M&&e<=O.GRAND_UP_TO_M?"grand":void 0}}class b{static METRES_PER_DEGREE=111320;static NAMED_NATURES={Silo:"Silo"};static DEFAULT_HEIGHT_M=6;static FLOOR_HEIGHT_M=3;static FINE_M=.5;static COARSE_M=1;static MAX_CELLS=4e4;static RECTANGLE_FILL=.9;static buildings(t,e,o,s=12,n=300,a=[]){const r=[];for(const h of b.reached(t,a,e,o)){const c=h.feature,l=Number(c.properties.nombre_d_etages),f=Number(c.properties.hauteur),M=Number.isFinite(f)&&f>0?f:Number.isFinite(l)&&l>0?l*b.FLOOR_HEIGHT_M:b.DEFAULT_HEIGHT_M,{style:d,builtYear:g}=O.ofMap(c.properties);for(const E of b.rectanglesOf(h.rings,M,s)){const p=T.of(c.properties.materiaux_des_murs,"wall"),N=T.of(c.properties.materiaux_de_la_toiture,"roof"),y=b.NAMED_NATURES[String(c.properties.nature??"")];r.push({...E,...y?{name:y}:{},...Number.isFinite(l)&&l>0?{floors:l}:{},...p?{wallMaterial:p}:{},...N?{roofMaterial:N}:{},...d?{style:d}:{},...g!==void 0?{builtYear:g}:{}})}}const i=h=>Math.hypot(h.eastM,h.northM);if(r.length>n){const h=c=>(c.heightM+6)*Math.sqrt(c.widthM*c.lengthM)/Math.max(i(c),50);r.sort((c,l)=>h(l)-h(c)),r.length=n}return r.sort((h,c)=>i(h)-i(c)),r}static named(t,e,o){const s=e.map(n=>({name:typeof n.properties.toponyme=="string"?n.properties.toponyme:"",rings:b.rings(n,o)})).filter(n=>n.name.length>0&&n.rings.length>0);return s.length===0?t:t.map(n=>{const a=s.find(r=>b.inside(n.eastM,n.northM,r.rings));return a?{...n,name:a.name}:n})}static reached(t,e,o,s){const n=t.map(i=>({feature:i,rings:b.rings(i,o)})).filter(i=>i.rings.length>0),a=n.map(i=>b.reach(i.rings)<=s),r=e.filter(i=>typeof i.properties.toponyme=="string"&&i.properties.toponyme.length>0).map(i=>b.rings(i,o)).filter(i=>i.length>0);if(r.length>0){const i=n.map(c=>{const l=c.rings[0],f=l.reduce((d,g)=>d+g.east,0)/l.length,M=l.reduce((d,g)=>d+g.north,0)/l.length;return r.findIndex(d=>b.inside(f,M,d))}),h=new Set(i.filter((c,l)=>c>=0&&a[l]));i.forEach((c,l)=>{h.has(c)&&(a[l]=!0)})}return n.filter((i,h)=>a[h])}static reach(t){if(b.inside(0,0,t))return 0;let e=1/0;for(const o of t)for(let s=0;s+1<o.length;s++){const n=o[s],a=o[s+1],r=a.east-n.east,i=a.north-n.north,h=r*r+i*i>0?Math.max(0,Math.min(1,-(n.east*r+n.north*i)/(r*r+i*i))):0;e=Math.min(e,Math.hypot(n.east+h*r,n.north+h*i))}return e}static inside(t,e,o){let s=0;for(const n of o)for(let a=0;a+1<n.length;a++){const r=n[a],i=n[a+1];r.north<=e!=i.north<=e&&r.east+(e-r.north)/(i.north-r.north)*(i.east-r.east)>t&&s++}return s%2===1}static rings(t,e){const o=t.geometry,s=o.type==="Polygon"?[o.coordinates]:o.type==="MultiPolygon"?o.coordinates:[],n=Math.cos(e.lat*Math.PI/180),a=[];for(const r of s)for(const i of r)a.push(i.map(([h,c])=>({east:(h-e.lng)*b.METRES_PER_DEGREE*n,north:(c-e.lat)*b.METRES_PER_DEGREE})));return a}static rectanglesOf(t,e,o){let s=1/0,n=-1/0,a=1/0,r=-1/0;for(const f of t)for(const M of f)s=Math.min(s,M.east),n=Math.max(n,M.east),a=Math.min(a,M.north),r=Math.max(r,M.north);let i=b.FINE_M;(n-s)*(r-a)/(i*i)>b.MAX_CELLS&&(i=b.COARSE_M);const h=[],c=[];for(let f=a+i/2;f<r;f+=i){const M=[];for(const d of t)for(let g=0;g+1<d.length;g++){const E=d[g],p=d[g+1];E.north<=f!=p.north<=f&&M.push(E.east+(f-E.north)/(p.north-E.north)*(p.east-E.east))}M.sort((d,g)=>d-g);for(let d=0;d+1<M.length;d+=2)for(let g=Math.ceil((M[d]-i/2)/i)*i+i/2;g<M[d+1];g+=i)h.push(g),c.push(f)}if(h.length*i*i<o)return[];const l=t.flatMap(f=>f.slice(0,-1).map((M,d)=>({from:M,to:f[d+1]})));return D.ofPoints(h,c,new Array(h.length).fill(e),i,o,b.RECTANGLE_FILL,l)}}class st{id="ign-lidar-topo";name="IGN LiDAR HD + BD TOPO";attribution="Canopy © IGN, LiDAR HD; buildings, bridges and lines © IGN, BD TOPO (Licence Ouverte 2.0), as surveyed on days the services do not give";creditUrl="https://geoservices.ign.fr/lidarhd";contemporary=!0;platform;furniture;constructor(t={},e){this.platform=new C(t),this.furniture=e}covers(t,e){return C.covers(t,e)}later(t,e){return u.later(this.furniture,t,e)}async getSurroundings(t,e){if(!this.covers(t.lat,t.lng))throw new X("no-coverage","The IGN's surveys cover France only");const o=C.radius(e),[s,n,a,r,i,h]=await Promise.allSettled([this.platform.lidar(t,o),this.platform.vectors(t,o,!0),this.platform.photo(t,o),this.furniture?.near(t,e)??Promise.resolve(void 0),this.platform.laserDate(t),this.platform.photoDate(t)]),c=C.lidarRadius(o);if(s.status==="rejected"&&n.status==="rejected")throw s.reason;const l=s.status==="fulfilled"?s.value:void 0,f=n.status==="fulfilled"?n.value:void 0,M=f!==void 0&&f.buildings.length===0&&f.bridges.length===0&&f.lines.length===0;if(s.status==="rejected"&&s.reason instanceof X&&s.reason.reason==="no-coverage"&&M)throw s.reason;return{trees:l?new k(l.heights,l.vegetation,l.size,l.size).trees({metresPerPixel:l.metresPerPixel,radiusM:c}):[],buildings:this.roofed(this.buildings(l,f,t,o),l,a.status==="fulfilled"?a.value:void 0),bridges:f?j.bridges(f,t,o,l?.structures):[],lines:f?j.lines(f,t,o,l?.structures):[],...r.status==="fulfilled"?r.value:{},dates:{...s.status==="fulfilled"&&i.status==="fulfilled"&&i.value?{laser:i.value}:{},...a.status==="fulfilled"&&h.status==="fulfilled"&&h.value?{photo:h.value}:{},...f?.mapDate?{map:f.mapDate}:{},...r.status==="fulfilled"&&u.found(r.value)?{lamps:u.today()}:{}}}}roofed(t,e,o){return T.fit(O.fit(R.fit(t,e,o)))}buildings(t,e,o,s){const n=e?b.buildings(e.buildings,o,s,void 0,void 0,e.zones):[],a=n.length>0||t===void 0?n:new D(t.heights,t.building,t.size,t.size).buildings({metresPerPixel:t.metresPerPixel,radiusM:C.lidarRadius(s),maxBuildings:300});return e?b.named(a,e.zones,o):a}}class ot{id="ign-bd-topo";name="IGN BD TOPO";attribution="Buildings, bridges and lines © IGN, BD TOPO (Licence Ouverte 2.0), as drawn on a day the service does not give";creditUrl="https://geoservices.ign.fr/bdtopo";contemporary=!0;platform;furniture;constructor(t={},e){this.platform=new C(t),this.furniture=e}covers(t,e){return C.covers(t,e)}later(t,e){return u.later(this.furniture,t,e)}async getSurroundings(t,e){if(!this.covers(t.lat,t.lng))throw new X("no-coverage","BD TOPO covers France only");const o=C.radius(e),[s,n,a,r]=await Promise.all([this.platform.vectors(t,o,!0),this.platform.photo(t,o).catch(()=>{}),this.furniture?.near(t,e),this.platform.photoDate(t)]);return{trees:[],buildings:T.fit(O.fit(R.fit(b.named(b.buildings(s.buildings,t,o,void 0,void 0,s.zones),s.zones,t),void 0,n))),bridges:j.bridges(s,t,o,void 0),lines:j.lines(s,t,o,void 0),...a,dates:{...s.mapDate?{map:s.mapDate}:{},...n&&r?{photo:r}:{},...u.found(a)?{lamps:u.today()}:{}}}}}class S{static ROOF_SHAPES={flat:"flat",gabled:"gable",gambrel:"gable",saltbox:"gable","half-hipped":"hip",hipped:"hip",pyramidal:"hip",mansard:"hip",round:"gable"};static WALL_MATERIALS={brick:"brick",stone:"stone",granite:"stone",sandstone:"stone",limestone:"stone",concrete:"concrete",cement_block:"block",block:"block",wood:"wood",timber_framing:"wood"};static ROOF_MATERIALS={roof_tiles:"tile",tiles:"tile",tile:"tile",slate:"slate",metal:"zinc",zinc:"zinc",tin:"zinc",copper:"zinc",concrete:"concrete",eternit:"other"};static COLOURS={white:"#e8e6e0",grey:"#8c8c8a",gray:"#8c8c8a",black:"#3a3a3a",red:"#a8483a",brown:"#6e4f38",beige:"#d6c9a8",yellow:"#d8c070",orange:"#c9773a",green:"#5f7a52",blue:"#506a8a",tan:"#c0a37a",cream:"#e6dcc0",pink:"#c99a96",silver:"#b4b6b6"};static height(t){const e=Number.parseFloat((t??"").replace(",","."));return Number.isFinite(e)&&e>=2&&e<=500?e:void 0}static levels(t){const e=Number.parseInt(t??"",10);return Number.isFinite(e)&&e>=1&&e<=150?e:void 0}static roofShape(t){return S.ROOF_SHAPES[(t??"").trim().toLowerCase()]}static wallMaterial(t){return S.WALL_MATERIALS[(t??"").trim().toLowerCase()]}static roofMaterial(t){return S.ROOF_MATERIALS[(t??"").trim().toLowerCase()]}static colour(t){const e=(t??"").trim().toLowerCase();return/^#[0-9a-f]{6}$/.test(e)?e:/^#[0-9a-f]{3}$/.test(e)?`#${e[1]}${e[1]}${e[2]}${e[2]}${e[3]}${e[3]}`:S.COLOURS[e]}}class W{id="osm-buildings";name="OpenStreetMap buildings";attribution="Buildings © OpenStreetMap contributors (ODbL), as drawn on the day of the data, which a recording is not";creditUrl="https://www.openstreetmap.org/copyright";contemporary=!0;static MAX_RADIUS_M=1500;static MIN_AREA_M2=12;static MAX_BUILDINGS=300;client;furniture;constructor(t={},e){this.client=new Q(t),this.furniture=e}covers(){return!0}later(t,e){return u.later(this.furniture,t,e)}async getSurroundings(t,e){const o=Math.min(e,W.MAX_RADIUS_M);let s;try{s=await this.client.query(`[out:json][timeout:30];(way["building"](around:${o},${t.lat},${t.lng});relation["building"]["type"="multipolygon"](around:${o},${t.lat},${t.lng}););out geom;`)}catch(r){throw new X("unreachable",r instanceof Error?r.message:String(r))}const n=await this.furniture?.near(t,e),a=(s.osm3s?.timestamp_osm_base??"").slice(0,10);return{trees:[],buildings:T.fit(O.fit(W.buildings(s,t,o))),bridges:[],lines:[],...n,dates:{.../^\d{4}-\d{2}-\d{2}$/.test(a)?{map:a}:{},...u.found(n)?{lamps:u.today()}:{}}}}static buildings(t,e,o){const s=[];for(const n of t.elements??[]){const a=W.ringsOf(n);if(a.length===0)continue;const r=n.tags??{},i=S.levels(r["building:levels"]),h=S.height(r.height),c={geometry:{type:"Polygon",coordinates:a},properties:{...h?{hauteur:h}:{},...i?{nombre_d_etages:i}:{}}};for(const l of b.buildings([c],e,o,W.MIN_AREA_M2,50))s.push(W.described(l,r,h!==void 0))}return s.sort((n,a)=>Math.hypot(n.eastM,n.northM)-Math.hypot(a.eastM,a.northM)),s.slice(0,W.MAX_BUILDINGS)}static ringsOf(t){const e=s=>{if(!s||s.length<4)return;const n=s.map(i=>[i.lon,i.lat]),a=n[0],r=n[n.length-1];return a[0]===r[0]&&a[1]===r[1]?n:void 0};if(t.type==="way"){const s=e(t.geometry);return s?[s]:[]}return(t.members??[]).filter(s=>s.role==="outer").map(s=>e(s.geometry)).filter(s=>s!==void 0).slice(0,1)}static described(t,e,o){const s=S.wallMaterial(e["building:material"]),n=S.roofMaterial(e["roof:material"]),a=S.colour(e["building:colour"]),r=S.colour(e["roof:colour"])??T.roofColor(n),i=S.roofShape(e["roof:shape"]),h=a?{color:a}:void 0;let c,l=t.heightM;if(i==="gable"||i==="hip"){const d=S.height(e["roof:height"]),g=Math.round((d??Math.min(5,Math.max(1.5,.29*Math.min(t.widthM,t.lengthM))))*10)/10;o||(l=Math.round((t.heightM+g)*10)/10),c={shape:i,riseM:g,...e["roof:orientation"]==="across"?{ridge:"depth"}:{},...r?{color:r}:{}}}else(i==="flat"||r)&&(c={shape:"flat",riseM:0,...r?{color:r}:{}});const{style:f,builtYear:M}=O.ofOsm(e);return{...t,heightM:l,...f?{style:f}:{},...M!==void 0?{builtYear:M}:{},...e.name?{name:e.name}:{},...s?{wallMaterial:s}:{},...n?{roofMaterial:n}:{},...h?{facade:h}:{},...c?{roof:c}:{}}}}class L{credit={name:"Ville de Paris, Éclairage public",url:"https://opendata.paris.fr/explore/dataset/eclairage-public/",licence:"ODbL",of:"lamps"};static BOUNDS={south:48.8156,north:48.9022,west:2.2241,east:2.4698};static ENDPOINT="https://opendata.paris.fr/api/explore/v2.1/catalog/datasets/eclairage-public/records";static PAGE=100;static MAX=150;static MAX_PAGES=4;static METRES_PER_DEGREE=111320;static SAME_COLUMN_M=.5;static MIN_HEIGHT_M=2;fetchImpl;constructor(t){this.fetchImpl=t??fetch.bind(globalThis)}covers(t,e){const o=L.BOUNDS;return t>=o.south&&t<=o.north&&e>=o.west&&e<=o.east}async lampsNear(t,e){const o=[];let s=[];for(let n=0;n<L.MAX_PAGES&&s.length<L.MAX;n++){const a=await this.fetchImpl(L.query(t,e,L.PAGE,n*L.PAGE));if(!a.ok)throw new Error(`opendata.paris.fr refused (${a.status})`);const r=(await a.json()).results??[];if(o.push(...r),s=L.lampsFrom(o,t),r.length<L.PAGE)break}return s.slice(0,L.MAX)}static query(t,e,o,s){const n=`geom'POINT(${t.lng.toFixed(6)} ${t.lat.toFixed(6)})'`,a=new URLSearchParams({select:"geo_point_2d,lib_ouvrag,lampe_temperature_couleur,lampe_flux,support_hauteur",where:`within_distance(geo_point_2d,${n},${Math.round(e)}m)`,order_by:`distance(geo_point_2d,${n})`,limit:String(o),offset:String(s)});return`${L.ENDPOINT}?${a}`}static lampsFrom(t,e){const o=Math.cos(e.lat*Math.PI/180),s=a=>{const r=typeof a=="number"?a:Number.parseFloat(a??"");return Number.isFinite(r)&&r>0?r:void 0},n=[];for(const a of t){const r=a.geo_point_2d;if(!r||a.lib_ouvrag==="Projecteur")continue;const i=Math.round((r.lon-e.lng)*L.METRES_PER_DEGREE*o*10)/10,h=Math.round((r.lat-e.lat)*L.METRES_PER_DEGREE*10)/10,c=s(a.lampe_flux),l=n.find(d=>Math.hypot(d.eastM-i,d.northM-h)<L.SAME_COLUMN_M);if(l){c!==void 0&&(l.lumens=(l.lumens??0)+c);continue}const f=s(a.lampe_temperature_couleur),M=s(a.support_hauteur);n.push({eastM:i,northM:h,...M!==void 0&&M>=L.MIN_HEIGHT_M?{heightM:M}:{},...f!==void 0?{colorTemperatureK:f}:{},...c!==void 0?{lumens:c}:{},...a.lib_ouvrag==="Console"?{mount:"wall"}:{}})}return n}}class _{constructor(t,e){this.roads=t,this.fetchImpl=e??fetch.bind(globalThis)}credit={name:"Ville de Paris, Signalisation lumineuse tricolore",url:"https://opendata.paris.fr/explore/dataset/signalisation-tricolore/",licence:"ODbL",of:"signals"};static BOUNDS={south:48.8156,north:48.9022,west:2.2241,east:2.4698};static ENDPOINT="https://opendata.paris.fr/api/explore/v2.1/catalog/datasets/signalisation-tricolore/records";static PAGE=100;static MAX_PAGES=5;static MAX=160;static METRES_PER_DEGREE=111320;static SAME_POST_M=.8;static SEARCH_M=15;static PEDESTRIAN_ALONG_M=.4;fetchImpl;covers(t,e){const o=_.BOUNDS;return t>=o.south&&t<=o.north&&e>=o.west&&e<=o.east}async signalsNear(t,e){const o=(e+_.SEARCH_M)/_.METRES_PER_DEGREE,s=o/Math.cos(t.lat*Math.PI/180),[n,a]=await Promise.all([this.lenses(t,e),this.roads.getRoads({south:t.lat-o,north:t.lat+o,west:t.lng-s,east:t.lng+s})]);return _.signalsFrom(n,a,t)}async lenses(t,e){const o=[];for(let s=0;s<_.MAX_PAGES;s++){const n=await this.fetchImpl(_.query(t,e,_.PAGE,s*_.PAGE));if(!n.ok)throw new Error(`opendata.paris.fr refused (${n.status})`);const a=(await n.json()).results??[];if(o.push(...a),a.length<_.PAGE)break}return o}static query(t,e,o,s){const n=`geom'POINT(${t.lng.toFixed(6)} ${t.lat.toFixed(6)})'`,a=new URLSearchParams({select:"geo_point_2d,lib_regime",where:`within_distance(geo_point_2d,${n},${Math.round(e)}m)`,order_by:`distance(geo_point_2d,${n})`,limit:String(o),offset:String(s)});return`${_.ENDPOINT}?${a}`}static signalsFrom(t,e,o){const s=Math.cos(o.lat*Math.PI/180),n=(h,c)=>[(c-o.lng)*_.METRES_PER_DEGREE*s,(h-o.lat)*_.METRES_PER_DEGREE],a=[];for(const h of t){if(!h.geo_point_2d)continue;const c=n(h.geo_point_2d.lat,h.geo_point_2d.lon),l=(h.lib_regime??"").toUpperCase(),f=/ROUGE|JAUNE|VERT/.test(l),M=/PASSEZ|ATTENDEZ/.test(l);if(!f&&!M)continue;let d=a.find(g=>Math.hypot(g.at[0]-c[0],g.at[1]-c[1])<_.SAME_POST_M);d||a.push(d={at:c,vehicles:0,pedestrians:0}),f&&d.vehicles++,M&&d.pedestrians++}const r=e.map(h=>({way:h,points:h.points.map(c=>n(c.lat,c.lng))})),i=[];for(const h of a){const c=_.nearestRoad(h.at,r);if(!c)continue;const[l,f]=c.unit,M=_.heading(c.unit),d=(h.at[0]-c.foot[0])*f-(h.at[1]-c.foot[1])*l>=0,g=c.way.direction,E=g==="forward"?M:g==="backward"?(M+180)%360:d?M:(M+180)%360,p=y=>Math.round(y*10)/10,N=y=>p((y%360+360)%360);if(h.vehicles>0&&i.push({eastM:p(h.at[0]),northM:p(h.at[1]),headingDeg:N(E+180),for:"vehicles",phase:K.phaseOf(E)}),h.pedestrians>0){const y=_.heading([c.foot[0]-h.at[0],c.foot[1]-h.at[1]]),m=h.vehicles>0?_.PEDESTRIAN_ALONG_M:0;i.push({eastM:p(h.at[0]+l*m),northM:p(h.at[1]+f*m),headingDeg:N(Number.isNaN(y)?M+90:y),for:"pedestrians",phase:K.phaseOf(M)})}}return i.sort((h,c)=>Math.hypot(h.eastM,h.northM)-Math.hypot(c.eastM,c.northM)).slice(0,_.MAX)}static nearestRoad(t,e){let o;for(const{way:s,points:n}of e)for(let a=1;a<n.length;a++){const[r,i]=n[a-1],[h,c]=n[a],l=Math.hypot(h-r,c-i);if(l===0)continue;const f=[(h-r)/l,(c-i)/l],M=Math.max(0,Math.min(l,(t[0]-r)*f[0]+(t[1]-i)*f[1])),d=[r+f[0]*M,i+f[1]*M],g=Math.hypot(t[0]-d[0],t[1]-d[1]);g<=_.SEARCH_M&&(!o||g<o.distance)&&(o={way:s,unit:f,foot:d,distance:g})}return o}static heading([t,e]){return t===0&&e===0?Number.NaN:Math.round((Math.atan2(t,e)*180/Math.PI+360)%360*10)/10}}const q=[{id:"ign-lidar-topo",name:"IGN LiDAR HD + BD TOPO",credit:"© IGN, LiDAR HD and BD TOPO, Licence Ouverte 2.0; street lamps © OpenStreetMap contributors",creditUrl:"https://geoservices.ign.fr/lidarhd",create:()=>new I(new st({},new u({},U.TOWN_LAMPS,U.TOWN_SIGNALS)))},{id:"ign-lidar-hd",name:"IGN LiDAR HD",credit:"© IGN, LiDAR HD, Licence Ouverte 2.0; street lamps © OpenStreetMap contributors",creditUrl:"https://geoservices.ign.fr/lidarhd",create:()=>new I(new et({},new u({},U.TOWN_LAMPS,U.TOWN_SIGNALS)))},{id:"ign-bd-topo",name:"IGN BD TOPO",credit:"© IGN, BD TOPO, Licence Ouverte 2.0; street lamps © OpenStreetMap contributors",creditUrl:"https://geoservices.ign.fr/bdtopo",create:()=>new I(new ot({},new u({},U.TOWN_LAMPS,U.TOWN_SIGNALS)))},{id:"osm-buildings",name:"OpenStreetMap buildings",credit:"Buildings and street lamps © OpenStreetMap contributors (ODbL)",creditUrl:"https://www.openstreetmap.org/copyright",create:()=>new I(new W({},new u({},U.TOWN_LAMPS,U.TOWN_SIGNALS)))}];class U{static DEFAULT_ID=q[0].id;static WORLD_ID="osm-buildings";static TOWN_LAMPS=[new L];static TOWN_SIGNALS=[new _(new B)];static NONE="none";static byId(t){return t===U.NONE?void 0:q.find(e=>e.id===t)??q[0]}static providerFor(t,e,o){const s=U.byId(t)?.create();if(t!==void 0&&t!==U.DEFAULT_ID)return s?.covers(e,o)?s:void 0;const n=q.find(r=>r.id===U.WORLD_ID).create(),a=[s,n].filter(r=>r!==void 0&&r.covers(e,o));return a.length>1?new tt(a):a[0]}}export{q as SURROUNDINGS_SOURCES,U as SurroundingsSources};
@@ -1,2 +0,0 @@
1
- import{A as ct,p as lt,q as U,R as L,r as P,t as ht,u as ut}from"./rr0-sighting-editor.mjs";import{C as Y}from"./ContrailGrowth-CuAzwIoc.js";class A{static OCTAVES=[63,125,250,500,1e3,2e3,4e3,8e3];static STANDARD={temperatureC:15,relativeHumidity:.7,pressureKPa:101.325};static REFERENCE_PRESSURE_KPA=101.325;static REFERENCE_TEMPERATURE_K=293.15;static TRIPLE_POINT_K=273.16;static speedOfSound(t){return 20.0468*Math.sqrt(t+273.15)}static absorptionDbPerKm(t,e=A.STANDARD){const a=e.temperatureC+273.15,n=A.REFERENCE_TEMPERATURE_K,i=e.pressureKPa/A.REFERENCE_PRESSURE_KPA,r=10**(-6.8346*(A.TRIPLE_POINT_K/a)**1.261+4.6151),s=e.relativeHumidity*100*r/i,o=i*(24+40400*s*(.02+s)/(.391+s)),l=i*(a/n)**-.5*(9+280*s*Math.exp(-4.17*((a/n)**(-1/3)-1))),c=t*t;return 8.686*c*(184e-13*(1/i)*Math.sqrt(a/n)+(a/n)**-2.5*(.01275*Math.exp(-2239.1/a)/(o+c/o)+.1068*Math.exp(-3352/a)/(l+c/l)))*1e3}static aWeightingDb(t){const e=t*t,a=12194**2*e*e/((e+20.6**2)*Math.sqrt((e+107.7**2)*(e+737.9**2))*(e+12194**2));return 20*Math.log10(a)+2}static sumDb(t){return 10*Math.log10(t.reduce((e,a)=>e+10**(a/10),0))}}const dt=.25,$=.4,J=6,j=12,pt=3,x=.2,mt=.2,gt=24,At=3,Et=12,Z=1,ft=.7,Mt=1.5,bt=.8,Dt=1.3,Q=.9,tt=5,St=25,Rt=.5,Bt=.12,et=[.13,.31],vt=.16,Ot=1.6,It=3.6,at=1.1,Tt=.3,_t=1e3,nt=.7;class V{context;noiseBuffer;roughBuffers=new Map;voices=new Map;bus;reverb;reverbOut;level=1;master;paused=!0;requested=[];headingDeg=0;resume(){if(!this.context){if(typeof AudioContext>"u")return;try{this.context=new AudioContext}catch(t){console.warn("AircraftAudio: Web Audio unavailable, aircraft stay silent:",t);return}}ct.unlock(this.context),this.apply()}setLevel(t){this.level=t,this.master&&(this.master.gain.value=t)}setPaused(t){t!==this.paused&&(this.paused=t,this.apply())}setVoices(t,e=0){this.requested=t,this.headingDeg=e,this.apply()}dispose(){for(const t of[...this.voices.keys()])this.release(t);this.context?.close(),this.context=void 0,this.master=void 0,this.bus=void 0}apply(){const t=this.context;if(!t)return;const e=this.paused?[]:this.requested,a=new Set(e.map(n=>n.id));for(const n of[...this.voices.keys()])a.has(n)||this.release(n);for(const n of e){const i=this.voices.get(n.id)??this.build(t,n);this.retarget(t,i,n)}}build(t,e){const a=t.createGain();a.gain.value=0;let n;const i=this.busOf(t);typeof t.createStereoPanner=="function"?(n=t.createStereoPanner(),a.connect(n).connect(i)):a.connect(i);const r=t.createGain(),s=e.character?.modulationDepth??0;r.gain.value=1-s/2;const o=t.createOscillator();o.type="sine";const l=t.createGain();l.gain.value=s/2,o.connect(l).connect(r.gain),r.connect(a);const c=t.createBufferSource();c.buffer=this.noise(t),c.loop=!0,c.loopStart=Math.random()*J*.5;const d=[],u=[],h=[];for(const D of A.OCTAVES){const v=t.createBiquadFilter();v.type="bandpass",v.frequency.value=D,v.Q.value=Z;const C=t.createBiquadFilter();C.type="bandpass",C.frequency.value=D,C.Q.value=Z;const w=t.createGain();w.gain.value=0,c.connect(v).connect(C).connect(w).connect(r),d.push(v),u.push(C),h.push(w)}const p=[];for(const[D,v]of[[e.character?.toneHz,e.character?.toneShare],[e.character?.humHz,e.character?.humShare]])if(D!==void 0)for(let C=1;C<=At;C++){const w=t.createOscillator();w.type="sine",w.frequency.value=D*C;const W=t.createGain();W.gain.value=0,w.connect(W).connect(a),p.push({oscillator:w,gain:W,harmonic:C,baseHz:D,share:v??0})}const m=t.createGain();m.gain.value=0,m.connect(a.gain);const f=et.map(D=>{const v=t.createOscillator();return v.type="sine",v.frequency.value=D,v.connect(m),v}),b=t.createGain();b.gain.value=e.character?.roughness??x;const N=t.createBufferSource();N.buffer=this.roughTable(t,pt),N.loop=!0,N.loopStart=Math.random()*j*.5,N.connect(b).connect(r.gain);const _=t.createGain();_.gain.value=(e.character?.roughness??x)*mt;const R=t.createBufferSource();R.buffer=this.roughTable(t,gt),R.loop=!0,R.loopStart=Math.random()*j*.5,R.connect(_).connect(r.gain);let O;const G=this.busOf(t)&&this.reverb;G&&(O=t.createGain(),O.gain.value=0,a.connect(O).connect(G));const z=[c,N,R,o,...p.map(D=>D.oscillator),...f];for(const D of z)D.start();const q={nodes:[a,r,l,b,_,m,...p.map(D=>D.gain),...d,...u,...h,...O?[O]:[],...n?[n]:[],...z],sources:z,filters:d,seconds:u,gains:h,tones:p,lfo:o,lfoDepth:l,wander:f,wanderDepth:m,roughDepth:b,crackleDepth:_,beat:r,output:a,panner:n,send:O};return this.voices.set(e.id,q),q}retarget(t,e,a){const n=t.currentTime,i=(p,m)=>p.setTargetAtTime(m,n,dt),r=Math.min(Mt,Math.max(ft,a.dopplerRatio)),s=Math.min(Dt,Math.max(bt,Math.sqrt(a.dopplerRatio))),o=t.sampleRate*.45,l=a.bandAmplitudes.map((p,m)=>p*V.unweighting(A.OCTAVES[m])),c=Math.sqrt(l.reduce((p,m)=>p+m*m,0)),d=Math.min(1,Math.max(0,(a.distanceKm-tt)/(St-tt)));A.OCTAVES.forEach((p,m)=>{i(e.filters[m].frequency,Math.min(o,p*s)),i(e.seconds[m].frequency,Math.min(o,p*s)),i(e.gains[m].gain,l[m]*Math.sqrt(_t/p))});const u=a.character;for(const{oscillator:p,gain:m,harmonic:f,baseHz:b,share:N}of e.tones){const _=b*f;i(p.frequency,_*r);const R=_*r;i(m.gain,R<o?N*vt*l[V.bandOf(R)]/f:0)}u?.modulationHz!==void 0&&i(e.lfo.frequency,u.modulationHz*r);const h=c>0?nt*(1-Math.exp(-c/nt))/c:1;if(i(e.output.gain,h*(1-Tt*d)),i(e.wanderDepth.gain,h*Bt*d/et.length),e.send&&i(e.send.gain,Ot*d),e.panner){const p=(a.azimuthDeg-this.headingDeg)*Math.PI/180;i(e.panner.pan,Math.max(-Q,Math.min(Q,Math.sin(p)))*(1-Rt*d))}}static unweighting(t){return 10**(Math.min(Et,Math.max(0,-A.aWeightingDb(t)))/20)}static bandOf(t){let e=0;return A.OCTAVES.forEach((a,n)=>{Math.abs(Math.log(t/a))<Math.abs(Math.log(t/A.OCTAVES[e]))&&(e=n)}),e}roughTable(t,e){const a=this.roughBuffers.get(e);if(a)return a;const n=Math.floor(t.sampleRate*j),i=t.createBuffer(1,n,t.sampleRate),r=i.getChannelData(0),s=Array.from({length:j*e},()=>(Math.random()*2-1)**3),o=t.sampleRate/e;for(let l=0;l<r.length;l++){const c=l/o,d=Math.floor(c),u=c-d,h=u*u*(3-2*u);r[l]=s[d%s.length]*(1-h)+s[(d+1)%s.length]*h}return this.roughBuffers.set(e,i),i}roomImpulse(t){const e=Math.floor(t.sampleRate*It),a=t.createBuffer(2,e,t.sampleRate);for(let n=0;n<2;n++){const i=a.getChannelData(n);let r=0;for(let s=0;s<e;s++){const o=s/t.sampleRate,l=.6*Math.exp(-o/(at*2))+.04;r+=l*(Math.random()*2-1-r),i[s]=r*Math.exp(-o/at)}}return a}busOf(t){if(this.bus)return this.bus;const e=t.createGain();if(e.gain.value=this.level,e.connect(t.destination),this.master=e,typeof t.createConvolver=="function"){const a=t.createConvolver();a.buffer=this.roomImpulse(t);const n=t.createGain();n.gain.value=.9,a.connect(n),this.reverb=a,this.reverbOut=n}if(typeof t.createDynamicsCompressor=="function"){const a=t.createDynamicsCompressor();a.threshold.value=-6,a.knee.value=3,a.ratio.value=4,a.attack.value=.005,a.release.value=.25,a.connect(e),this.bus=a}else this.bus=e;return this.reverbOut?.connect(this.bus),this.bus}release(t){const e=this.voices.get(t);if(!e)return;this.voices.delete(t);const a=this.context;a&&(e.output.gain.setTargetAtTime(0,a.currentTime,$/3),setTimeout(()=>{for(const n of e.sources)try{n.stop()}catch{}for(const n of e.nodes)n.disconnect()},$*1e3*3))}noise(t){if(this.noiseBuffer)return this.noiseBuffer;const e=t.createBuffer(1,t.sampleRate*J,t.sampleRate),a=e.getChannelData(0);for(let n=0;n<a.length;n++)a[n]=Math.random()*2-1;return this.noiseBuffer=e,e}}class I{static BASE_DB_A=30;static WIND_DB_A=[[0,10],[1,28],[2,36],[3,40],[5,46],[8,52],[12,58],[20,66]];static RAIN_DB_A=[[0,0],[.1,42],[.3,50],[.6,58],[1,65]];static BED_RMS=.2;static MINIMUM_REFERENCE=.008;static WIND_BED_MIN_MS=1;static WIND_BED_FULL_MS=20;static dbA(t){const e=[I.BASE_DB_A,I.along(I.WIND_DB_A,t.windSpeed)];return(t.precipitationType==="rain"||t.precipitationType==="hail")&&e.push(I.along(I.RAIN_DB_A,t.precipitationIntensity)),10*Math.log10(e.filter(a=>a>0).reduce((a,n)=>a+10**(n/10),0))}static bedVolume(t){const e=t.windSpeed>I.WIND_BED_MIN_MS?Math.min(t.windSpeed/I.WIND_BED_FULL_MS,1):0,a=t.precipitationType==="hail"?Math.min(1,t.precipitationIntensity*1.3+.2):t.precipitationType==="rain"?t.precipitationIntensity:0;return Math.hypot(e,a)}static referenceAmplitude(t){return Math.max(I.BED_RMS*I.bedVolume(t),I.MINIMUM_REFERENCE)}static along(t,e){if(e<=t[0][0])return t[0][1];for(let a=1;a<t.length;a++)if(e<=t[a][0]){const[n,i]=t[a-1],[r,s]=t[a];return i+(s-i)*(e-n)/(r-n)}return t[t.length-1][1]}}class y{static TYPES={A318:["Airbus A318","airliner-narrow",34.1,31.4],A319:["Airbus A319","airliner-narrow",34.1,33.8],A320:["Airbus A320","airliner-narrow",34.1,37.6],A321:["Airbus A321","airliner-narrow",34.1,44.5],A19N:["Airbus A319neo","airliner-narrow",35.8,33.8],A20N:["Airbus A320neo","airliner-narrow",35.8,37.6],A21N:["Airbus A321neo","airliner-narrow",35.8,44.5],B737:["Boeing 737-700","airliner-narrow",34.3,33.6],B738:["Boeing 737-800","airliner-narrow",35.8,39.5],B739:["Boeing 737-900","airliner-narrow",35.8,42.1],B38M:["Boeing 737 MAX 8","airliner-narrow",35.9,39.5],B39M:["Boeing 737 MAX 9","airliner-narrow",35.9,42.2],B752:["Boeing 757-200","airliner-narrow",38,47.3],B753:["Boeing 757-300","airliner-narrow",38,54.4],B762:["Boeing 767-200","airliner-wide",47.6,48.5],B763:["Boeing 767-300","airliner-wide",47.6,54.9],B764:["Boeing 767-400","airliner-wide",51.9,61.4],B772:["Boeing 777-200","airliner-wide",60.9,63.7],B77L:["Boeing 777-200LR","airliner-wide",64.8,63.7],B77W:["Boeing 777-300ER","airliner-wide",64.8,73.9],B788:["Boeing 787-8","airliner-wide",60.1,56.7],B789:["Boeing 787-9","airliner-wide",60.1,62.8],B78X:["Boeing 787-10","airliner-wide",60.1,68.3],B744:["Boeing 747-400","airliner-wide",64.4,70.7],B748:["Boeing 747-8","airliner-wide",68.4,76.3],A306:["Airbus A300-600","airliner-wide",44.8,54.1],A310:["Airbus A310","airliner-wide",43.9,46.7],A332:["Airbus A330-200","airliner-wide",60.3,58.8],A333:["Airbus A330-300","airliner-wide",60.3,63.7],A338:["Airbus A330-800","airliner-wide",64,58.8],A339:["Airbus A330-900","airliner-wide",64,63.7],A343:["Airbus A340-300","airliner-wide",60.3,63.7],A346:["Airbus A340-600","airliner-wide",63.5,75.4],A359:["Airbus A350-900","airliner-wide",64.8,66.8],A35K:["Airbus A350-1000","airliner-wide",64.8,73.8],A388:["Airbus A380-800","airliner-wide",79.8,72.7],E170:["Embraer 170","regional-jet",26,29.9],E75L:["Embraer 175","regional-jet",26,31.7],E75S:["Embraer 175","regional-jet",26,31.7],E190:["Embraer 190","regional-jet",28.7,36.2],E195:["Embraer 195","regional-jet",28.7,38.7],E290:["Embraer 190-E2","regional-jet",33.7,36.2],E295:["Embraer 195-E2","regional-jet",33.7,41.5],CRJ2:["Bombardier CRJ200","regional-jet",21.2,26.8],CRJ7:["Bombardier CRJ700","regional-jet",23.2,32.3],CRJ9:["Bombardier CRJ900","regional-jet",24.9,36.2],CRJX:["Bombardier CRJ1000","regional-jet",26.2,39.1],AT72:["ATR 72","regional-turboprop",27.1,27.2],AT76:["ATR 72-600","regional-turboprop",27.1,27.2],AT45:["ATR 42","regional-turboprop",24.6,22.7],DH8D:["Dash 8 Q400","regional-turboprop",28.4,32.8],DH8C:["Dash 8-300","regional-turboprop",27.4,25.7],SF34:["Saab 340","regional-turboprop",21.4,19.7],B190:["Beechcraft 1900","regional-turboprop",17.7,17.6],C25A:["Cessna CitationJet CJ2","business-jet",14.3,14.4],C56X:["Cessna Citation Excel","business-jet",17.2,16],C68A:["Cessna Citation Latitude","business-jet",22,18.9],C550:["Cessna Citation II","business-jet",15.8,14.4],E55P:["Embraer Phenom 300","business-jet",15.9,15.6],E50P:["Embraer Phenom 100","business-jet",12.3,12.8],GLF5:["Gulfstream G550","business-jet",28.5,29.4],FA7X:["Dassault Falcon 7X","business-jet",26.2,23.4],CL60:["Bombardier Challenger 600","business-jet",19.6,20.9],LJ45:["Learjet 45","business-jet",14.6,17.7],H25B:["Hawker 800","business-jet",15.7,15.6],C172:["Cessna 172","light-piston",11,8.3],C152:["Cessna 152","light-piston",10.2,7.3],C182:["Cessna 182","light-piston",10.9,8.8],P28A:["Piper Cherokee","light-piston",10.7,7.2],PA34:["Piper Seneca","light-piston",11.8,8.7],SR20:["Cirrus SR20","light-piston",10.9,7.9],SR22:["Cirrus SR22","light-piston",11.7,7.9],S22T:["Cirrus SR22T","light-piston",11.7,7.9],DA40:["Diamond DA40","light-piston",11.6,8.1],DA42:["Diamond DA42","light-piston",13.4,8.6],BE20:["Beechcraft King Air 200","turboprop-light",16.6,13.3],BE58:["Beechcraft Baron","light-piston",11.5,9.1],C208:["Cessna Caravan","turboprop-light",15.9,11.5],PC12:["Pilatus PC-12","turboprop-light",16.3,14.4],TBM9:["Daher TBM 900","turboprop-light",12.8,10.7],EC35:["Airbus H135","helicopter-light",10.2,12.1],EC45:["Airbus H145","helicopter-medium",11,13.6],AS50:["Airbus H125","helicopter-light",10.7,12.9],EC30:["Airbus H130","helicopter-light",10.7,12.6],B407:["Bell 407","helicopter-light",10.7,12.7],B06:["Bell 206","helicopter-light",10.2,12],B429:["Bell 429","helicopter-medium",10.9,13],B505:["Bell 505","helicopter-light",10.4,11.9],R44:["Robinson R44","helicopter-light",10.1,11.7],R22:["Robinson R22","helicopter-light",7.7,8.8],A109:["Agusta A109","helicopter-medium",11,13],A139:["Leonardo AW139","helicopter-medium",13.8,16.7],S92:["Sikorsky S-92","helicopter-heavy",17.2,20.9],H60:["Sikorsky UH-60 Black Hawk","helicopter-heavy",16.4,19.8],T38:["Northrop T-38 Talon","military-jet",7.7,14.1],HAWK:["BAE Hawk","military-jet",9.4,11.9],GLID:["Glider","glider",17,7],BALL:["Balloon","balloon",15,20],ULAC:["Ultralight","ultralight",9.5,6],C42:["Ikarus C42","ultralight",9.4,6.3],DRON:["Drone","unmanned",1,.6]};static CATEGORIES={A1:["Light aircraft","light-piston",11,8.3],A2:["Small aircraft","business-jet",15,15],A3:["Large aircraft","airliner-narrow",34.1,37.6],A4:["High-vortex large aircraft","airliner-narrow",38,47.3],A5:["Heavy aircraft","airliner-wide",60.3,63.7],A6:["High-performance aircraft","military-jet",8,14],A7:["Rotorcraft","helicopter-medium",10.7,12.7],B1:["Glider","glider",17,7],B2:["Lighter-than-air","balloon",15,20],B4:["Ultralight","ultralight",9.5,6],B6:["Unmanned aircraft","unmanned",1.5,1]};static GENERIC={name:"Airliner",kind:"airliner-narrow",spanM:34.1,lengthM:37.6,basis:"nothing"};static of(t){const e=t?.type?.toUpperCase(),a=e?y.TYPES[e]:void 0;if(a)return{code:e,name:a[0],kind:a[1],spanM:a[2],lengthM:a[3],basis:"type"};const n=t?.category?y.CATEGORIES[t.category]:void 0;return n?{name:n[0],kind:n[1],spanM:n[2],lengthM:n[3],basis:"category"}:{...y.GENERIC}}static isHelicopter(t){return t.kind.startsWith("helicopter")}}class k{static DUSK_SUN_ELEVATION_DEG=-.83;static ALWAYS=new Set(["airliner-narrow","airliner-wide","regional-turboprop","regional-jet","business-jet"]);static NONE=new Set(["glider","balloon"]);static BRIGHTNESS={"light-piston":[.5,.2,.5],"turboprop-light":[.7,.4,.8],ultralight:[.4,.2,.4],unmanned:[0,.05,0],"helicopter-light":[1,1,1],"helicopter-medium":[1,1,1],"helicopter-heavy":[1,1,1],"military-jet":[1,1,1]};static lampsOn(t,e){if(k.NONE.has(t))return{navigation:!1,beacon:!1,strobes:!1};if(k.ALWAYS.has(t))return{navigation:!0,beacon:!0,strobes:!0};const a=e<k.DUSK_SUN_ELEVATION_DEG;return t==="unmanned"?{navigation:!1,beacon:!1,strobes:a}:{navigation:a,beacon:a,strobes:a}}static lights(t,e){const a=k.lampsOn(t.kind,e),n=t.kind.startsWith("helicopter"),i=lt.find(h=>h.id===(n?"helicopter":"airliner")).create(),[r,s]=n?[5,7]:[17,18],o=t.spanM/2/r,l=t.lengthM/2/s,[c,d,u]=k.BRIGHTNESS[t.kind]??[1,1,1];return i.filter(h=>h.id.startsWith("nav")?a.navigation:h.id.startsWith("strobe")?a.strobes:h.id.startsWith("beacon")?a.beacon:!0).filter(h=>!(h.id.startsWith("beacon")&&!a.beacon)).map(h=>{const p=h.id.startsWith("nav")?c:h.id.startsWith("strobe")?d:u;return{...h,offsetM:{x:h.offsetM.x*o,y:h.offsetM.y,z:h.offsetM.z*l},intensity:(h.intensity??1)*p}}).filter(h=>(h.intensity??1)>0)}static bodyColor(t){return t.kind==="military-jet"?"#8a8e94":t.kind.startsWith("helicopter")?"#c8ccd1":t.kind==="unmanned"?"#2c2e33":"#dde0e4"}}class F{static FAMILIES={"amvlab-a320":["A318","A319","A320","A321","A19N","A20N","A21N"],"amvlab-b737":["B732","B733","B734","B735","B736","B737","B738","B739","B37M","B38M","B39M","B3XM"],"amvlab-a350":["A359","A35K"],"amvlab-a380":["A388"],"amvlab-b787":["B788","B789","B78X"]};static BY_TYPE=new Map(Object.entries(F.FAMILIES).flatMap(([t,e])=>e.map(a=>[a,t])));static idOf(t){return t?F.BY_TYPE.get(t.toUpperCase()):void 0}}class M{static ID_PREFIX=U.ID_PREFIX;static MAX_OBJECTS=40;static FT_TO_M=.3048;static DEG=Math.PI/180;static from(t,e,a,n=M.MAX_OBJECTS,i={}){return new Ct(t,e,a,n,i).build()}static idOf(t,e){return U.idOf(t,e)}static keyOf(t){return U.keyOf(t)}static HEIGHT_OVER_LENGTH=.29;static sizeOf(t){return{widthM:t.spanM,lengthM:t.lengthM,heightM:t.lengthM*M.HEIGHT_OVER_LENGTH}}static offsetOf(t,e){const a=L.seenFrom(t,{lat:e.lat,lng:e.lng,heightM:e.altitudeFt*M.FT_TO_M}),n=a.distanceKm*1e3,i=n*Math.cos(a.altitudeDeg*M.DEG);return{eastM:i*Math.sin(a.azimuthDeg*M.DEG),northM:i*Math.cos(a.azimuthDeg*M.DEG),upM:n*Math.sin(a.altitudeDeg*M.DEG),altitudeDeg:a.altitudeDeg,distanceKm:a.distanceKm}}static segments(t){const e=[];let a=[];for(const n of t.points){const i=a[a.length-1];i&&n.t-i.t>P.MAX_GAP_S*1e3&&(e.push(a),a=[]),a.push(n)}return e.push(a),e.filter(n=>n.length>=2)}static bearingDeg(t,e){return(Math.atan2(e.eastM-t.eastM,e.northM-t.northM)/M.DEG+360)%360}}class Ct{constructor(t,e,a,n,i){this.tracks=t,this.observer=e,this.startMs=a,this.maxObjects=n,this.options=i}build(){const t=[];for(const a of this.tracks){const n=M.keyOf(a),i=this.options.models?.get(n)??y.of(void 0);M.segments(a).forEach((r,s)=>{const o=r.map(h=>({point:h,at:M.offsetOf(this.observer,h)}));if(!o.some(h=>h.at.altitudeDeg>=0))return;const l=o.map((h,p)=>({t:h.point.t-this.startMs,eastM:h.at.eastM,northM:h.at.northM,altitudeM:h.at.upM,headingDeg:h.point.trackDeg??(p+1<o.length?M.bearingDeg(h.at,o[p+1].at):M.bearingDeg(o[p-1].at,h.at))})),c=M.idOf(a,s),d=o[Math.floor(o.length/2)].point,u=this.options.sunElevationAt?.(d)??90;t.push({object:{id:c,kind:"aircraft",eastM:l[0].eastM,northM:l[0].northM,headingDeg:l[0].headingDeg,sizeM:M.sizeOf(i),model:F.idOf(i.code)?{id:F.idOf(i.code)}:void 0,color:k.bodyColor(i),lights:k.lights(i,u),track:l},presence:{fromMs:l[0].t,untilMs:l[l.length-1].t},flight:{icao:a.icao,nonIcao:a.nonIcao,points:r},closestKm:Math.min(...o.map(h=>h.at.distanceKm))})})}t.sort((a,n)=>a.closestKm-n.closestKm);const e=t.slice(0,this.maxObjects);return{objects:e.map(a=>a.object),presence:new Map(e.map(a=>[a.object.id,a.presence])),flights:new Map(e.map(a=>[a.object.id,a.flight])),total:t.length,shown:e.length}}}const ot=[{id:"turbofan-narrow-body",name:"Turbofan airliner, narrow-body",kinds:["airliner-narrow"],totalDbA:148,shapeDb:[-32,-17,-9,-6,-5,-7,-12,-22],character:{toneHz:1800,toneShare:.3,humHz:90,humShare:.7}},{id:"turbofan-wide-body",name:"Turbofan airliner, wide-body",kinds:["airliner-wide"],totalDbA:151,shapeDb:[-28,-14,-7,-4,-3,-6,-12,-22],character:{toneHz:1200,toneShare:.3,humHz:70,humShare:.7}},{id:"regional-jet",name:"Regional jet",kinds:["regional-jet"],totalDbA:144,shapeDb:[-32,-17,-9,-5,-4,-6,-11,-21],character:{toneHz:1900,toneShare:.3,humHz:95,humShare:.7}},{id:"business-jet",name:"Business jet",kinds:["business-jet"],totalDbA:141,shapeDb:[-30,-15,-8,-4,-3,-4,-9,-19],character:{toneHz:2500,toneShare:.25,humHz:110,humShare:.7}},{id:"turboprop",name:"Turboprop",kinds:["regional-turboprop","turboprop-light"],totalDbA:138,shapeDb:[-14,-9,-8,-6,-8,-13,-20,-28],character:{toneHz:80,toneShare:.5}},{id:"light-piston",name:"Light piston aircraft",kinds:["light-piston"],totalDbA:130,shapeDb:[-18,-9,-5,-4,-8,-14,-22,-30],character:{toneHz:80,toneShare:.4}},{id:"ultralight",name:"Ultralight",kinds:["ultralight"],totalDbA:124,shapeDb:[-16,-8,-5,-4,-9,-15,-23,-31],character:{toneHz:140,toneShare:.4}},{id:"helicopter-light",name:"Light helicopter",kinds:["helicopter-light"],totalDbA:134,shapeDb:[-15,-8,-4,-3,-6,-10,-16,-24],character:{modulationHz:20,modulationDepth:.5}},{id:"helicopter-medium",name:"Medium helicopter",kinds:["helicopter-medium"],totalDbA:138,shapeDb:[-14,-7,-4,-3,-6,-10,-16,-24],character:{modulationHz:22,modulationDepth:.5}},{id:"helicopter-heavy",name:"Heavy helicopter",kinds:["helicopter-heavy"],totalDbA:144,shapeDb:[-12,-6,-4,-4,-7,-11,-17,-25],character:{modulationHz:17,modulationDepth:.5}},{id:"military-jet",name:"Military jet",kinds:["military-jet"],totalDbA:152,shapeDb:[-26,-12,-6,-3,-2,-3,-7,-15]},{id:"glider",name:"Glider",kinds:["glider"],totalDbA:85,shapeDb:[-30,-22,-15,-10,-8,-8,-14,-22]},{id:"balloon",name:"Hot-air balloon",kinds:["balloon"],totalDbA:100,shapeDb:[-25,-15,-9,-5,-3,-6,-12,-20]},{id:"unmanned",name:"Unmanned aircraft",kinds:["unmanned"],totalDbA:88,shapeDb:[-40,-30,-20,-12,-6,-3,-3,-8],character:{toneHz:450,toneShare:1}}],it=ot.map(T=>({id:T.id,name:T.name,soundPowerA:T.shapeDb.map(t=>t+T.totalDbA-A.sumDb(T.shapeDb)),character:T.character}));class g{static DEFAULT_AMBIENT_DB_A=35;static DETECTION_MARGIN_DB=3;static AMBIENT_SHAPE_DB=[-12,-7,-5,-5,-7,-11,-17,-25];static HEARING_FLOOR_DB_A=0;static ITERATIONS=30;static CONVERGED_MS=.5;static VELOCITY_STEP_MS=500;static noiseOfKind(t){const e=ot.find(a=>a.kinds.includes(t));return it.find(a=>a.id===(e?.id??"turbofan-narrow-body"))}static bandsAt(t,e,a=A.STANDARD){const n=20*Math.log10(Math.max(e*1e3,1))+11;return A.OCTAVES.map((i,r)=>t.soundPowerA[r]-n-A.absorptionDbPerKm(i,a)*e)}static couldBeHeard(t,e,a=g.DEFAULT_AMBIENT_DB_A,n=A.STANDARD){const i=g.ambientBands(a);return g.bandsAt(t,e,n).some((r,s)=>r>=Math.max(i[s]+g.DETECTION_MARGIN_DB,g.HEARING_FLOOR_DB_A))}static ambientBands(t){const e=g.AMBIENT_SHAPE_DB,a=A.sumDb(e);return e.map(n=>t+n-a)}static heardAt(t,e,a,n={}){const i=n.air??A.STANDARD,r=A.speedOfSound(i.temperatureC),s=t.points[t.points.length-1]?.t;if(s===void 0)return;let o=Math.min(a,s),l=P.positionAt(t,o);if(!l)return;let c=L.seenFrom(e,l.geo);for(let R=0;R<g.ITERATIONS;R++){const O=a-c.distanceKm*1e3*1e3/r,G=Math.abs(O-o);if(o=O,l=P.positionAt(t,o),!l)return;if(c=L.seenFrom(e,l.geo),G<g.CONVERGED_MS)break}const d=P.positionAt(t,a),u=d?L.seenFrom(e,d.geo):c,h=n.noise??it[0],p=n.ambientDbA??g.DEFAULT_AMBIENT_DB_A,m=g.ambientBands(p),f=g.bandsAt(h,c.distanceKm,i),b=f.map((R,O)=>R>=Math.max(m[O]+g.DETECTION_MARGIN_DB,g.HEARING_FLOOR_DB_A)),N=f.indexOf(Math.max(...f)),_=b.lastIndexOf(!0);return{track:t,audible:b.some(Boolean),levelDbA:A.sumDb(f),bandsDbA:f,ambientDbA:p,delayS:(a-o)/1e3,emittedAtMs:o,sound:c,seen:u,lagDeg:g.angleBetween(c,u),dopplerRatio:g.doppler(t,e,o,r),dominantHz:A.OCTAVES[N],cutoffHz:_<0?void 0:A.OCTAVES[_]}}static profile(t,e,a,n,i=2e3,r={}){const s=[];let o,l,c=a;for(let d=a;d<=n;d+=i){const u=g.heardAt(t,e,d,r);u&&(!l||u.levelDbA>l.levelDbA)&&(l=u,c=d),u?.audible?o?o.untilMs=d:s.push(o={fromMs:d,untilMs:d}):o=void 0}return{track:t,audible:s,peakDbA:l?.levelDbA??-1/0,peakAtMs:c,peakDelayS:l?.delayS??0}}static angleBetween(t,e){const a=c=>{const d=c.altitudeDeg*Math.PI/180,u=c.azimuthDeg*Math.PI/180;return[Math.cos(d)*Math.sin(u),Math.cos(d)*Math.cos(u),Math.sin(d)]},[n,i,r]=a(t),[s,o,l]=a(e);return Math.acos(Math.min(1,Math.max(-1,n*s+i*o+r*l)))*180/Math.PI}static doppler(t,e,a,n){const i=g.VELOCITY_STEP_MS,r=P.positionAt(t,a-i),s=P.positionAt(t,a+i);if(!r||!s)return 1;const o=L.seenFrom(e,r.geo).distanceKm*1e3,l=L.seenFrom(e,s.geo).distanceKm*1e3;return 1/(1-(o-l)/(2*i/1e3)/n)}}class Lt{static at(t,e,a,n,i={}){const r=P.seenFrom(t,a,n);if(!r)return;const s=y.of(e),o=g.heardAt(t,a,n,{noise:g.noiseOfKind(s.kind),...i});return{hex:`${t.nonIcao?"~":""}${t.icao.toString(16).padStart(6,"0")}`,registration:e?.registration,typeCode:s.code??e?.type,name:s.basis==="nothing"?void 0:s.name,kind:s.kind,basis:s.basis,military:e?.military===!0,restricted:e?.restricted===!0,altitudeFt:r.altitudeFt,groundSpeedKt:r.groundSpeedKt,trackDeg:r.trackDeg,sky:r.sky,angularRateDegPerS:r.angularRateDegPerS,hearing:o&&{audible:o.audible,levelDbA:o.levelDbA,ambientDbA:o.ambientDbA,delayS:o.delayS,lagDeg:o.lagDeg,dopplerRatio:o.dopplerRatio,cutoffHz:o.cutoffHz,dominantHz:o.dominantHz}}}}class S{static REFERENCE_AMPLITUDE=.02;static MASKING_RANGE_DB=6;static KNEE_DB=20;static COMPRESSION_RATIO=1.5;static EXPANSION_RATIO=1.8;static DEFAULT_MAX_VOICES=4;static candidates(t,e,a,n,i={}){const r=new Set;for(const[s,o]of t){const l=g.noiseOfKind(y.of(e.get(a(o))).kind);let c=1/0;for(const d of o.points)c=Math.min(c,L.seenFrom(n,{lat:d.lat,lng:d.lng,heightM:d.altitudeFt*.3048}).distanceKm);g.couldBeHeard(l,c,i.ambientDbA,i.air)&&r.add(s)}return r}static voices(t,e,a,n,i,r,s={}){const o=[];for(const l of t){const c=e.get(l);if(!c||s.only?.(l)===!1)continue;const d=s.kindOf?.(l)??y.of(a.get(n(c))).kind,u=g.noiseOfKind(d),h=g.heardAt(c,i,r,{...s,noise:u});h?.audible&&o.push({id:l,kind:d,bandAmplitudes:S.bandAmplitudes(h.bandsDbA,h.ambientDbA,s.referenceAmplitude),levelDbA:h.levelDbA,distanceKm:h.sound.distanceKm,dopplerRatio:h.dopplerRatio,azimuthDeg:h.sound.azimuthDeg,elevationDeg:h.sound.altitudeDeg,character:u.character})}return o.sort((l,c)=>c.levelDbA-l.levelDbA).slice(0,s.maxVoices??S.DEFAULT_MAX_VOICES)}static bandAmplitudes(t,e,a=S.REFERENCE_AMPLITUDE){const n=g.ambientBands(e),i=g.DETECTION_MARGIN_DB,r=A.sumDb(t),s=r-e,o=s>=S.KNEE_DB?S.KNEE_DB+(s-S.KNEE_DB)/S.COMPRESSION_RATIO:S.KNEE_DB-(S.KNEE_DB-s)*S.EXPANSION_RATIO,l=a*10**(o/20);return t.map((c,d)=>{const u=Math.min(1,Math.max(0,(c-n[d]-i+S.MASKING_RANGE_DB)/(2*S.MASKING_RANGE_DB)));return u*u*(3-2*u)*l*10**((c-r)/20)})}static BANDS_HZ=A.OCTAVES}class K{static ENGLISH={unnamed:"Aircraft {hex}",altitude:"{value} ft",speed:"{value} kt",heading:"heading {value}°",position:"{distance} km away, {elevation}° above the horizon, {bearing}",heard:"Heard at {level} dB(A), left the aircraft {delay} s ago, {lag}° behind it: {character}{pitch}",rumble:"a low rumble, nothing above {cutoff} Hz",muffled:"a dull noise, nothing above {cutoff} Hz",broad:"a broad roar",pitchHigher:", pitch {percent} % higher",pitchLower:", pitch {percent} % lower",inaudible:"Not audible here: {level} dB(A) against {ambient} dB(A) of ambient noise",soundUnknown:"Its sound cannot be worked out: the aircraft was not recorded yet when it left",contrailPersistent:"Leaves a trail that lasts: the air is supersaturated over ice ({rhi} % over ice)",contrailShort:"Leaves a short-lived trail: the air is dry over ice ({rhi} % over ice)",military:"military",restricted:"identity withheld by its owner",candidate:"A compatible candidate, not an identification"};static RUMBLE_BELOW_HZ=500;static DULL_BELOW_HZ=2e3;static PITCH_NOTICED=.03;static text(t,e,a,n){const i=(u,h=0)=>u.toLocaleString(n,{maximumFractionDigits:h}),r=(u,h)=>u.replace(/\{(\w+)\}/g,(p,m)=>h[m]??`{${m}}`),s=[],o=[t.registration,t.name].filter(Boolean).join(" · ");s.push(o||r(e.unnamed,{hex:t.hex}));const l=[r(e.altitude,{value:i(Math.round(t.altitudeFt/100)*100)}),t.groundSpeedKt===void 0?void 0:r(e.speed,{value:i(Math.round(t.groundSpeedKt))}),t.trackDeg===void 0?void 0:r(e.heading,{value:i(Math.round(t.trackDeg))})].filter(Boolean);s.push(l.join(" · ")),s.push(r(e.position,{distance:i(t.sky.distanceKm,t.sky.distanceKm<10?1:0),elevation:i(Math.round(t.sky.altitudeDeg)),bearing:a(t.sky.azimuthDeg)}));const c=t.hearing;if(!c)s.push(e.soundUnknown);else if(!c.audible)s.push(r(e.inaudible,{level:i(Math.round(c.levelDbA)),ambient:i(Math.round(c.ambientDbA))}));else{const u=c.cutoffHz??0,h=u<=K.RUMBLE_BELOW_HZ?e.rumble:u<=K.DULL_BELOW_HZ?e.muffled:e.broad,p=c.dopplerRatio-1,m=Math.abs(p)<K.PITCH_NOTICED?"":r(p>0?e.pitchHigher:e.pitchLower,{percent:i(Math.round(Math.abs(p)*100))});s.push(r(e.heard,{level:i(Math.round(c.levelDbA)),delay:i(Math.round(c.delayS)),lag:i(Math.round(c.lagDeg)),character:r(h,{cutoff:i(u)}),pitch:m}))}t.contrail&&s.push(r(t.contrail.persistent?e.contrailPersistent:e.contrailShort,{rhi:i(Math.round(t.contrail.iceRelativeHumidity*100))}));const d=[t.military?e.military:void 0,t.restricted?e.restricted:void 0].filter(Boolean);return d.length>0&&s.push(d.join(" · ")),s.push(e.candidate),s.join(`
2
- `)}}class X{static EFFICIENCY={"airliner-narrow":.34,"airliner-wide":.38,"regional-jet":.32,"business-jet":.3,"military-jet":.22,unknown:.34};static efficiencyOf(t){return X.EFFICIENCY[t]}}class E{static EMISSION_INDEX_WATER=1.25;static COMBUSTION_HEAT=432e5;static AIR_HEAT_CAPACITY=1004;static MOLAR_MASS_RATIO=.622;static FT_TO_M=.3048;static TROPOPAUSE_M=11e3;static TROPOPAUSE_HPA=226.32;static ISOTHERMAL_SCALE_HEIGHT_M=6341.62;static pressureAtAltitudeFt(t){const e=t*E.FT_TO_M;return e<=E.TROPOPAUSE_M?1013.25*(1-225577e-10*e)**5.25588:E.TROPOPAUSE_HPA*Math.exp(-(e-E.TROPOPAUSE_M)/E.ISOTHERMAL_SCALE_HEIGHT_M)}static saturationOverWaterPa(t){const e=t+273.15;return Math.exp(54.842763-6763.22/e-4.21*Math.log(e)+367e-6*e+Math.tanh(.0415*(e-218.8))*(53.878-1331.22/e-9.44523*Math.log(e)+.014025*e))}static saturationOverIcePa(t){const e=t+273.15;return Math.exp(9.550426-5723.265/e+3.53068*Math.log(e)-.00728332*e)}static iceRelativeHumidity(t,e){return e*E.saturationOverWaterPa(t)/E.saturationOverIcePa(t)}static mixingSlope(t,e){return E.EMISSION_INDEX_WATER*E.AIR_HEAT_CAPACITY*t*100/(E.MOLAR_MASS_RATIO*E.COMBUSTION_HEAT*(1-e))}static criticalTemperatureC(t,e){const a=Math.log(E.mixingSlope(t,e)-.053);return-46.46+9.43*a+.72*a*a}static requiredHumidity(t,e,a){const n=E.criticalTemperatureC(t,e);return(E.mixingSlope(t,e)*(a-n)+E.saturationOverWaterPa(n))/E.saturationOverWaterPa(a)}static evaluate(t,e){const a=E.criticalTemperatureC(t.pressureHpa,e),n=E.requiredHumidity(t.pressureHpa,e,t.temperatureC),i=E.iceRelativeHumidity(t.temperatureC,t.relativeHumidity),r=t.temperatureC<a&&t.relativeHumidity>=n;return{forms:r,persistent:r&&i>=1,criticalTemperatureC:a,requiredHumidity:n,iceRelativeHumidity:i}}}class H{static HOLD_MS=36e5;static DEG=Math.PI/180;static GAS_CONSTANT_OVER_GRAVITY=287.05/9.80665;static at(t,e,a){if(t.length===0)return;const n=t[0],i=t[t.length-1];if(e<n.t-H.HOLD_MS||e>i.t+H.HOLD_MS)return;const r=t.findIndex(h=>h.t>e),s=r===0?t[0]:t[(r===-1?t.length:r)-1],o=r===-1||r===0?s:t[r],l=H.atLevel(s,a),c=H.atLevel(o,a);if(!l||!c)return;const d=o.t>s.t?Math.min(1,Math.max(0,(e-s.t)/(o.t-s.t))):0,u=(h,p)=>h+(p-h)*d;return{pressureHpa:a,temperatureC:u(l.temperatureC,c.temperatureC),relativeHumidity:u(l.relativeHumidity,c.relativeHumidity),driftEastMs:u(l.driftEastMs,c.driftEastMs),driftNorthMs:u(l.driftNorthMs,c.driftNorthMs),shearPerS:u(l.shearPerS,c.shearPerS)}}static atLevel(t,e){const a=t.levels;for(let n=0;n+1<a.length;n++){const i=a[n],r=a[n+1];if(e>i.pressureHpa||e<r.pressureHpa)continue;const s=(Math.log(i.pressureHpa)-Math.log(e))/(Math.log(i.pressureHpa)-Math.log(r.pressureHpa)),o=(h,p)=>h+(p-h)*s,l=h=>{const p=h.windFromDeg*H.DEG;return{east:-h.windSpeedMs*Math.sin(p),north:-h.windSpeedMs*Math.cos(p)}},c=l(i),d=l(r),u=H.GAS_CONSTANT_OVER_GRAVITY*((i.temperatureC+r.temperatureC)/2+273.15)*Math.log(i.pressureHpa/r.pressureHpa);return{pressureHpa:e,temperatureC:o(i.temperatureC,r.temperatureC),relativeHumidity:o(i.relativeHumidity,r.relativeHumidity),driftEastMs:o(c.east,d.east),driftNorthMs:o(c.north,d.north),shearPerS:Math.hypot(d.east-c.east,d.north-c.north)/u}}}}class Pt{static plan(t,e,a,n){if(a.length===0)return[];const i=[];for(const r of t.objects){const s=t.flights.get(r.id),o=r.track;if(!s||!o||o.length!==s.points.length)continue;const l=e?.get(U.keyOf(s))??y.of(void 0),c=X.efficiencyOf(l.kind);if(c===void 0)continue;const d=[];o.forEach((u,h)=>{const p=s.points[h],m=E.pressureAtAltitudeFt(p.altitudeFt),f=H.at(a,n+u.t,m),b=f&&E.evaluate(f,c);d.push({tMs:u.t,eastM:u.eastM,northM:u.northM,upM:u.altitudeM??0,forms:b?.forms??!1,persistent:b?.persistent??!1,lifetimeS:b?Y.lifetimeS(b.iceRelativeHumidity):0,driftEastMs:f?.driftEastMs??0,driftNorthMs:f?.driftNorthMs??0,shearPerS:f?.shearPerS??Y.TYPICAL_SHEAR_PER_S,iceRelativeHumidity:b?.iceRelativeHumidity??0})}),d.some((u,h)=>u.forms&&d[h+1]?.forms)&&i.push({id:r.id,spanM:l.spanM,points:d})}return i}}const st=[500,400,300,250,200,150],Nt=["temperature","relative_humidity","wind_speed","wind_direction"],yt="2022-01-01",rt=.25;class wt{fetchImpl;baseUrl;cache=new Map;constructor(t={}){this.fetchImpl=t.fetchImpl??fetch.bind(globalThis),this.baseUrl=t.baseUrl??"https://historical-forecast-api.open-meteo.com/v1/forecast"}between(t,e,a){const n=new Date(e).toISOString().slice(0,10);if(n<yt)return Promise.resolve({status:"outside"});const i=new Date(a).toISOString().slice(0,10),s=`${`${Math.round(t.lat/rt)},${Math.round(t.lng/rt)}`}|${n}|${i}`;let o=this.cache.get(s);return o||(o=this.read(t,n,i),this.cache.set(s,o),o.then(l=>{l.status==="failed"&&this.cache.delete(s)})),o}async read(t,e,a){const n=st.flatMap(s=>Nt.map(o=>`${o}_${s}hPa`)),i=new URLSearchParams({latitude:String(t.lat),longitude:String(t.lng),start_date:e,end_date:a,hourly:n.join(","),wind_speed_unit:"ms",timezone:"UTC"}),r=`${this.baseUrl}?${i}`;try{const s=await this.fetchImpl(r);if(!s.ok)return{status:"failed"};const o=await s.json();return this.decode(o,{id:"open-meteo-forecast",name:"Open-Meteo (historical forecast)",url:r})}catch{return{status:"failed"}}}decode(t,e){const a=t.hourly;if(!a?.time)return{status:"outside"};const n=[];return a.time.forEach((i,r)=>{const s=[];for(const o of st){const l=p=>a[`${p}_${o}hPa`]?.[r],c=l("temperature"),d=l("relative_humidity"),u=l("wind_speed"),h=l("wind_direction");if([c,d,u,h].some(p=>p==null))return;s.push({pressureHpa:o,temperatureC:c,relativeHumidity:d/100,windSpeedMs:u,windFromDeg:h})}n.push({t:Date.parse(`${i}Z`),levels:s})}),n.length>0?{status:"found",samples:n,source:e}:{status:"outside"}}}const Ft=[{id:"open-meteo-forecast",name:"Open-Meteo (historical forecast)",credit:"Weather data by Open-Meteo.com, CC BY 4.0",creditUrl:"https://open-meteo.com/en/docs/historical-forecast-api",create:()=>new wt}];class B{static DEFAULT_KIND="airliner-narrow";static STEP_MS=1e3;static LEAD_MS=12e4;static FT_PER_M=1/.3048;static ID_PREFIX="decor:";tracks=new Map;static kindOf(t,e){if(t.kind!=="aircraft"||!B.flies(t))return;const a=t.aircraftSound??e??B.DEFAULT_KIND;return a==="silent"?void 0:a}static flies(t){return(t.track??[]).some(e=>(e.altitudeM??0)>0)}voices(t,e,a,n={},i=()=>{}){const r=t.event.place?.[0];if(!r)return[];const s=new Map,o=new Map,l=Math.max(t.observerTrack.duration,(t.event.durationSeconds??0)*1e3);for(const c of t.decor){const d=B.kindOf(c,i(c));if(!d)continue;const u=`${B.ID_PREFIX}${c.id}`;s.set(u,this.trackOf(c,u,r,l)),o.set(u,d)}for(const c of this.tracks.keys())s.has(c)||this.tracks.delete(c);return s.size===0?[]:S.voices(new Set(s.keys()),s,new Map,c=>String(c.icao),a,e,{...n,kindOf:c=>o.get(c)})}trackOf(t,e,a,n){const i=JSON.stringify([t.track,t.eastM,t.northM,t.headingDeg,a.lat,a.lng,n]),r=this.tracks.get(e);if(r?.key===i)return r.track;const s=[];for(let u=0;u<=n;u+=B.STEP_MS)s.push(B.pointAt(t,u,a));(s.length===0||s[s.length-1].t<n)&&s.push(B.pointAt(t,n,a));const o=s[0],l=s[1]??o,c=u=>(l[u]-o[u])/(l.t-o.t||1);for(let u=B.STEP_MS*10;u<=B.LEAD_MS;u+=B.STEP_MS*10)s.unshift({t:-u,lat:o.lat-c("lat")*u,lng:o.lng-c("lng")*u,altitudeFt:Math.max(0,o.altitudeFt-c("altitudeFt")*u)});const d={icao:B.hash(e),nonIcao:!0,points:s};return this.tracks.set(e,{key:i,track:d}),d}static pointAt(t,e,a){const n=ht(t,e),i=ut(n.eastM,-n.northM,a.lat,a.lng);return{t:e,lat:i.lat,lng:i.lng,altitudeFt:n.altitudeM*B.FT_PER_M}}static hash(t){let e=0;for(let a=0;a<t.length;a++)e=e*31+t.charCodeAt(a)>>>0;return e}}export{V as AircraftAudio,Pt as AircraftContrails,y as AircraftModels,I as AmbientNoise,B as DecorAircraftHearing,M as TrafficDecor,Lt as TrafficInfos,S as TrafficSound,K as TrafficTooltip,Ft as UPPER_AIR_SOURCES};