@jjlmoya/utils-science 1.51.0 → 1.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/scripts/crystal-lattice-catalog-translations.mjs +1 -0
- package/src/category/i18n/es.ts +3 -4
- package/src/category/i18n/fr.ts +2 -2
- package/src/category/i18n/it.ts +2 -2
- package/src/category/i18n/pt.ts +2 -2
- package/src/category/index.ts +25 -25
- package/src/components/PreviewNavSidebar.astro +1 -1
- package/src/components/PreviewToolbar.astro +1 -1
- package/src/data.ts +1 -1
- package/src/env.d.ts +1 -1
- package/src/layouts/PreviewLayout.astro +1 -1
- package/src/pages/index.astro +1 -1
- package/src/tests/bibliography_wellformed_export.test.ts +46 -0
- package/src/tests/category_seo_quality.test.ts +76 -0
- package/src/tests/faq_count.test.ts +19 -19
- package/src/tests/i18n_coverage.test.ts +36 -36
- package/src/tests/mocks/astro_mock.js +1 -1
- package/src/tests/no_h1_in_components.test.ts +1 -1
- package/src/tests/script_density.test.ts +94 -94
- package/src/tests/seo_length.test.ts +24 -24
- package/src/tests/seo_parity.test.ts +5 -5
- package/src/tests/seo_translation_completeness.test.ts +76 -0
- package/src/tests/seo_wellformed_export.test.ts +65 -0
- package/src/tests/spanish_leakage.test.ts +175 -175
- package/src/tool/asteroid-impact/component.astro +251 -251
- package/src/tool/asteroid-impact/helpers.ts +17 -17
- package/src/tool/asteroid-impact/i18n/de.ts +2 -2
- package/src/tool/asteroid-impact/i18n/en.ts +2 -2
- package/src/tool/asteroid-impact/i18n/es.ts +2 -2
- package/src/tool/asteroid-impact/i18n/fr.ts +2 -2
- package/src/tool/asteroid-impact/i18n/id.ts +2 -2
- package/src/tool/asteroid-impact/i18n/it.ts +2 -2
- package/src/tool/asteroid-impact/i18n/ja.ts +2 -2
- package/src/tool/asteroid-impact/i18n/ko.ts +2 -2
- package/src/tool/asteroid-impact/i18n/nl.ts +2 -2
- package/src/tool/asteroid-impact/i18n/pl.ts +2 -2
- package/src/tool/asteroid-impact/i18n/pt.ts +2 -2
- package/src/tool/asteroid-impact/i18n/ru.ts +2 -2
- package/src/tool/asteroid-impact/i18n/sv.ts +2 -2
- package/src/tool/asteroid-impact/i18n/tr.ts +2 -2
- package/src/tool/asteroid-impact/i18n/zh.ts +2 -2
- package/src/tool/asteroid-impact/script.ts +262 -262
- package/src/tool/asteroid-impact/seo.astro +15 -15
- package/src/tool/asteroid-impact/ui.ts +69 -69
- package/src/tool/black-hole-event-horizon-simulator/i18n/de.ts +249 -241
- package/src/tool/black-hole-event-horizon-simulator/i18n/fr.ts +252 -247
- package/src/tool/black-hole-event-horizon-simulator/i18n/id.ts +259 -259
- package/src/tool/black-hole-event-horizon-simulator/i18n/it.ts +255 -252
- package/src/tool/black-hole-event-horizon-simulator/i18n/ja.ts +254 -252
- package/src/tool/black-hole-event-horizon-simulator/i18n/ko.ts +258 -258
- package/src/tool/black-hole-event-horizon-simulator/i18n/nl.ts +256 -252
- package/src/tool/black-hole-event-horizon-simulator/i18n/pl.ts +258 -258
- package/src/tool/black-hole-event-horizon-simulator/i18n/pt.ts +256 -252
- package/src/tool/black-hole-event-horizon-simulator/i18n/ru.ts +258 -258
- package/src/tool/black-hole-event-horizon-simulator/i18n/sv.ts +257 -252
- package/src/tool/black-hole-event-horizon-simulator/i18n/tr.ts +256 -251
- package/src/tool/black-hole-event-horizon-simulator/i18n/zh.ts +261 -252
- package/src/tool/cellular-renewal/component.astro +126 -126
- package/src/tool/cellular-renewal/i18n/de.ts +1 -1
- package/src/tool/cellular-renewal/i18n/en.ts +1 -1
- package/src/tool/cellular-renewal/i18n/es.ts +1 -1
- package/src/tool/cellular-renewal/i18n/fr.ts +1 -1
- package/src/tool/cellular-renewal/i18n/id.ts +1 -1
- package/src/tool/cellular-renewal/i18n/it.ts +1 -1
- package/src/tool/cellular-renewal/i18n/ja.ts +1 -1
- package/src/tool/cellular-renewal/i18n/ko.ts +1 -1
- package/src/tool/cellular-renewal/i18n/nl.ts +1 -1
- package/src/tool/cellular-renewal/i18n/pl.ts +1 -1
- package/src/tool/cellular-renewal/i18n/pt.ts +1 -1
- package/src/tool/cellular-renewal/i18n/ru.ts +1 -1
- package/src/tool/cellular-renewal/i18n/sv.ts +1 -1
- package/src/tool/cellular-renewal/i18n/tr.ts +1 -1
- package/src/tool/cellular-renewal/i18n/zh.ts +1 -1
- package/src/tool/cellular-renewal/seo.astro +15 -15
- package/src/tool/colony-counter/i18n/de.ts +1 -1
- package/src/tool/colony-counter/i18n/en.ts +1 -1
- package/src/tool/colony-counter/i18n/es.ts +1 -1
- package/src/tool/colony-counter/i18n/fr.ts +1 -1
- package/src/tool/colony-counter/i18n/id.ts +1 -1
- package/src/tool/colony-counter/i18n/it.ts +1 -1
- package/src/tool/colony-counter/i18n/ja.ts +1 -1
- package/src/tool/colony-counter/i18n/ko.ts +1 -1
- package/src/tool/colony-counter/i18n/nl.ts +1 -1
- package/src/tool/colony-counter/i18n/pl.ts +1 -1
- package/src/tool/colony-counter/i18n/pt.ts +1 -1
- package/src/tool/colony-counter/i18n/ru.ts +1 -1
- package/src/tool/colony-counter/i18n/sv.ts +1 -1
- package/src/tool/colony-counter/i18n/tr.ts +1 -1
- package/src/tool/colony-counter/i18n/zh.ts +1 -1
- package/src/tool/colony-counter/seo.astro +15 -15
- package/src/tool/conway-life-rule-lab/component.astro +1 -1
- package/src/tool/conway-life-rule-lab/i18n/de.ts +145 -141
- package/src/tool/conway-life-rule-lab/i18n/es.ts +146 -142
- package/src/tool/conway-life-rule-lab/i18n/fr.ts +146 -142
- package/src/tool/conway-life-rule-lab/i18n/id.ts +146 -145
- package/src/tool/conway-life-rule-lab/i18n/it.ts +146 -145
- package/src/tool/conway-life-rule-lab/i18n/ja.ts +146 -145
- package/src/tool/conway-life-rule-lab/i18n/ko.ts +146 -145
- package/src/tool/conway-life-rule-lab/i18n/nl.ts +147 -145
- package/src/tool/conway-life-rule-lab/i18n/pl.ts +147 -145
- package/src/tool/conway-life-rule-lab/i18n/pt.ts +147 -145
- package/src/tool/conway-life-rule-lab/i18n/ru.ts +147 -145
- package/src/tool/conway-life-rule-lab/i18n/sv.ts +147 -145
- package/src/tool/conway-life-rule-lab/i18n/tr.ts +147 -145
- package/src/tool/conway-life-rule-lab/i18n/zh.ts +147 -145
- package/src/tool/conway-life-rule-lab/logic/LifeLabRuntime.ts +2 -2
- package/src/tool/cosmic-inflation/i18n/ru.ts +105 -105
- package/src/tool/crystal-lattice-structure-finder/i18n/de.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/en.ts +1 -1
- package/src/tool/crystal-lattice-structure-finder/i18n/es.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/fr.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/id.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/it.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/ja.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/ko.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/nl.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/pl.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/pt.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/ru.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/sv.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/tr.ts +217 -217
- package/src/tool/crystal-lattice-structure-finder/i18n/zh.ts +217 -217
- package/src/tool/double-slit-decoherence/i18n/de.ts +181 -181
- package/src/tool/double-slit-decoherence/i18n/fr.ts +180 -180
- package/src/tool/double-slit-decoherence/i18n/id.ts +181 -181
- package/src/tool/double-slit-decoherence/i18n/it.ts +180 -180
- package/src/tool/double-slit-decoherence/i18n/ja.ts +181 -181
- package/src/tool/double-slit-decoherence/i18n/ko.ts +181 -181
- package/src/tool/double-slit-decoherence/i18n/nl.ts +181 -181
- package/src/tool/double-slit-decoherence/i18n/pl.ts +181 -181
- package/src/tool/double-slit-decoherence/i18n/pt.ts +178 -174
- package/src/tool/double-slit-decoherence/i18n/ru.ts +180 -180
- package/src/tool/double-slit-decoherence/i18n/sv.ts +176 -172
- package/src/tool/double-slit-decoherence/i18n/tr.ts +180 -180
- package/src/tool/double-slit-decoherence/i18n/zh.ts +181 -181
- package/src/tool/dyson-sphere-energy-capture/component.astro +253 -253
- package/src/tool/dyson-sphere-energy-capture/i18n/de.ts +194 -194
- package/src/tool/dyson-sphere-energy-capture/i18n/en.ts +6 -6
- package/src/tool/dyson-sphere-energy-capture/i18n/es.ts +6 -6
- package/src/tool/dyson-sphere-energy-capture/i18n/fr.ts +194 -194
- package/src/tool/dyson-sphere-energy-capture/i18n/id.ts +195 -195
- package/src/tool/dyson-sphere-energy-capture/i18n/it.ts +194 -194
- package/src/tool/dyson-sphere-energy-capture/i18n/ja.ts +194 -190
- package/src/tool/dyson-sphere-energy-capture/i18n/ko.ts +194 -193
- package/src/tool/dyson-sphere-energy-capture/i18n/nl.ts +197 -197
- package/src/tool/dyson-sphere-energy-capture/i18n/pl.ts +168 -166
- package/src/tool/dyson-sphere-energy-capture/i18n/pt.ts +194 -193
- package/src/tool/dyson-sphere-energy-capture/i18n/ru.ts +195 -193
- package/src/tool/dyson-sphere-energy-capture/i18n/sv.ts +195 -193
- package/src/tool/dyson-sphere-energy-capture/i18n/tr.ts +168 -166
- package/src/tool/dyson-sphere-energy-capture/i18n/zh.ts +194 -193
- package/src/tool/epidemic-sir-simulator/i18n/de.ts +347 -347
- package/src/tool/epidemic-sir-simulator/i18n/es.ts +347 -347
- package/src/tool/epidemic-sir-simulator/i18n/fr.ts +347 -347
- package/src/tool/epidemic-sir-simulator/i18n/it.ts +346 -346
- package/src/tool/epidemic-sir-simulator/i18n/nl.ts +347 -347
- package/src/tool/epidemic-sir-simulator/i18n/ru.ts +347 -347
- package/src/tool/epidemic-sir-simulator/i18n/sv.ts +347 -347
- package/src/tool/epidemic-sir-simulator/i18n/zh.ts +347 -347
- package/src/tool/exoplanet-biosignature-detector/i18n/de.ts +186 -186
- package/src/tool/exoplanet-biosignature-detector/i18n/en.ts +195 -195
- package/src/tool/exoplanet-biosignature-detector/i18n/es.ts +194 -194
- package/src/tool/exoplanet-biosignature-detector/i18n/fr.ts +183 -183
- package/src/tool/exoplanet-biosignature-detector/i18n/id.ts +193 -193
- package/src/tool/exoplanet-biosignature-detector/i18n/it.ts +194 -194
- package/src/tool/exoplanet-biosignature-detector/i18n/ja.ts +194 -194
- package/src/tool/exoplanet-biosignature-detector/i18n/ko.ts +194 -194
- package/src/tool/exoplanet-biosignature-detector/i18n/nl.ts +194 -194
- package/src/tool/exoplanet-biosignature-detector/i18n/pl.ts +144 -144
- package/src/tool/exoplanet-biosignature-detector/i18n/pt.ts +146 -146
- package/src/tool/exoplanet-biosignature-detector/i18n/ru.ts +143 -143
- package/src/tool/exoplanet-biosignature-detector/i18n/sv.ts +144 -144
- package/src/tool/exoplanet-biosignature-detector/i18n/tr.ts +145 -145
- package/src/tool/exoplanet-biosignature-detector/i18n/zh.ts +194 -194
- package/src/tool/global-albedo-snowball-simulator/component.astro +1 -1
- package/src/tool/global-albedo-snowball-simulator/i18n/de.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/fr.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/id.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/it.ts +87 -87
- package/src/tool/global-albedo-snowball-simulator/i18n/ja.ts +87 -87
- package/src/tool/global-albedo-snowball-simulator/i18n/ko.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/nl.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/pl.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/pt.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/ru.ts +165 -161
- package/src/tool/global-albedo-snowball-simulator/i18n/sv.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/tr.ts +169 -169
- package/src/tool/global-albedo-snowball-simulator/i18n/zh.ts +169 -169
- package/src/tool/lorenz-attractor/i18n/de.ts +144 -143
- package/src/tool/lorenz-attractor/i18n/fr.ts +144 -144
- package/src/tool/lorenz-attractor/i18n/id.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/it.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/ja.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/ko.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/nl.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/pl.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/pt.ts +142 -141
- package/src/tool/lorenz-attractor/i18n/ru.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/sv.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/tr.ts +149 -149
- package/src/tool/lorenz-attractor/i18n/zh.ts +149 -149
- package/src/tool/mandelbrot-fractal/i18n/de.ts +158 -158
- package/src/tool/mandelbrot-fractal/i18n/fr.ts +158 -158
- package/src/tool/mandelbrot-fractal/i18n/id.ts +159 -159
- package/src/tool/mandelbrot-fractal/i18n/it.ts +155 -151
- package/src/tool/mandelbrot-fractal/i18n/ja.ts +159 -159
- package/src/tool/mandelbrot-fractal/i18n/ko.ts +159 -159
- package/src/tool/mandelbrot-fractal/i18n/nl.ts +159 -159
- package/src/tool/mandelbrot-fractal/i18n/pl.ts +157 -153
- package/src/tool/mandelbrot-fractal/i18n/pt.ts +158 -158
- package/src/tool/mandelbrot-fractal/i18n/ru.ts +159 -159
- package/src/tool/mandelbrot-fractal/i18n/sv.ts +159 -150
- package/src/tool/mandelbrot-fractal/i18n/tr.ts +159 -159
- package/src/tool/mandelbrot-fractal/i18n/zh.ts +159 -159
- package/src/tool/microwave-detector/component.astro +238 -238
- package/src/tool/microwave-detector/i18n/de.ts +1 -1
- package/src/tool/microwave-detector/i18n/en.ts +1 -1
- package/src/tool/microwave-detector/i18n/es.ts +1 -1
- package/src/tool/microwave-detector/i18n/fr.ts +1 -1
- package/src/tool/microwave-detector/i18n/id.ts +1 -1
- package/src/tool/microwave-detector/i18n/it.ts +1 -1
- package/src/tool/microwave-detector/i18n/ja.ts +1 -1
- package/src/tool/microwave-detector/i18n/ko.ts +1 -1
- package/src/tool/microwave-detector/i18n/nl.ts +1 -1
- package/src/tool/microwave-detector/i18n/pl.ts +1 -1
- package/src/tool/microwave-detector/i18n/pt.ts +1 -1
- package/src/tool/microwave-detector/i18n/ru.ts +1 -1
- package/src/tool/microwave-detector/i18n/sv.ts +1 -1
- package/src/tool/microwave-detector/i18n/tr.ts +1 -1
- package/src/tool/microwave-detector/i18n/zh.ts +1 -1
- package/src/tool/microwave-detector/seo.astro +15 -15
- package/src/tool/natural-selection-drift/component.astro +135 -135
- package/src/tool/natural-selection-drift/i18n/de.ts +164 -160
- package/src/tool/natural-selection-drift/i18n/fr.ts +204 -204
- package/src/tool/natural-selection-drift/i18n/id.ts +156 -154
- package/src/tool/natural-selection-drift/i18n/it.ts +197 -193
- package/src/tool/natural-selection-drift/i18n/ja.ts +155 -154
- package/src/tool/natural-selection-drift/i18n/ko.ts +155 -154
- package/src/tool/natural-selection-drift/i18n/nl.ts +164 -163
- package/src/tool/natural-selection-drift/i18n/pl.ts +168 -166
- package/src/tool/natural-selection-drift/i18n/pt.ts +200 -195
- package/src/tool/natural-selection-drift/i18n/ru.ts +186 -184
- package/src/tool/natural-selection-drift/i18n/sv.ts +157 -154
- package/src/tool/natural-selection-drift/i18n/tr.ts +186 -184
- package/src/tool/natural-selection-drift/i18n/zh.ts +160 -154
- package/src/tool/natural-selection-drift/natural-selection-drift.css +563 -563
- package/src/tool/phase-diagram-critical-points/i18n/de.ts +178 -178
- package/src/tool/phase-diagram-critical-points/i18n/fr.ts +178 -178
- package/src/tool/phase-diagram-critical-points/i18n/id.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/it.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/ja.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/ko.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/nl.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/pl.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/pt.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/ru.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/sv.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/tr.ts +179 -179
- package/src/tool/phase-diagram-critical-points/i18n/zh.ts +179 -179
- package/src/tool/planet-atmosphere-survival/i18n/de.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/fr.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/id.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/it.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/ja.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/ko.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/nl.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/pl.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/pt.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/ru.ts +227 -223
- package/src/tool/planet-atmosphere-survival/i18n/sv.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/tr.ts +255 -255
- package/src/tool/planet-atmosphere-survival/i18n/zh.ts +255 -255
- package/src/tool/radioactive-decay/i18n/de.ts +168 -164
- package/src/tool/radioactive-decay/i18n/fr.ts +76 -75
- package/src/tool/radioactive-decay/i18n/id.ts +169 -165
- package/src/tool/radioactive-decay/i18n/it.ts +76 -74
- package/src/tool/radioactive-decay/i18n/ja.ts +168 -167
- package/src/tool/radioactive-decay/i18n/ko.ts +168 -167
- package/src/tool/radioactive-decay/i18n/nl.ts +170 -168
- package/src/tool/radioactive-decay/i18n/pl.ts +170 -168
- package/src/tool/radioactive-decay/i18n/pt.ts +169 -167
- package/src/tool/radioactive-decay/i18n/ru.ts +170 -168
- package/src/tool/radioactive-decay/i18n/sv.ts +170 -168
- package/src/tool/radioactive-decay/i18n/tr.ts +171 -168
- package/src/tool/radioactive-decay/i18n/zh.ts +171 -167
- package/src/tool/roche-limit-satellite-disruption/i18n/de.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/fr.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/id.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/it.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/ja.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/ko.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/nl.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/pl.ts +237 -229
- package/src/tool/roche-limit-satellite-disruption/i18n/pt.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/ru.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/sv.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/tr.ts +241 -241
- package/src/tool/roche-limit-satellite-disruption/i18n/zh.ts +241 -241
- package/src/tool/simulation-probability/component.astro +138 -138
- package/src/tool/simulation-probability/i18n/de.ts +1 -1
- package/src/tool/simulation-probability/i18n/en.ts +1 -1
- package/src/tool/simulation-probability/i18n/es.ts +1 -1
- package/src/tool/simulation-probability/i18n/fr.ts +1 -1
- package/src/tool/simulation-probability/i18n/id.ts +1 -1
- package/src/tool/simulation-probability/i18n/it.ts +1 -1
- package/src/tool/simulation-probability/i18n/ja.ts +1 -1
- package/src/tool/simulation-probability/i18n/ko.ts +1 -1
- package/src/tool/simulation-probability/i18n/nl.ts +1 -1
- package/src/tool/simulation-probability/i18n/pl.ts +1 -1
- package/src/tool/simulation-probability/i18n/pt.ts +1 -1
- package/src/tool/simulation-probability/i18n/ru.ts +1 -1
- package/src/tool/simulation-probability/i18n/sv.ts +1 -1
- package/src/tool/simulation-probability/i18n/tr.ts +1 -1
- package/src/tool/simulation-probability/i18n/zh.ts +1 -1
- package/src/tool/simulation-probability/seo.astro +15 -15
- package/src/tool/stellar-habitability-zone/i18n/ru.ts +189 -189
- package/src/tool/temperature-timeline/i18n/de.ts +2 -1
- package/src/tool/temperature-timeline/i18n/fr.ts +177 -177
- package/src/tool/temperature-timeline/i18n/it.ts +142 -141
- package/src/tool/temperature-timeline/i18n/pt.ts +3 -1
- package/src/tool/temperature-timeline/i18n/ru.ts +116 -114
- package/src/tool/three-body-problem/app.ts +4 -4
- package/src/tool/three-body-problem/component.astro +6 -6
- package/src/tool/twin-paradox-visualizer/i18n/de.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/es.ts +165 -165
- package/src/tool/twin-paradox-visualizer/i18n/fr.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/id.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/it.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/ja.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/ko.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/nl.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/pl.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/pt.ts +164 -160
- package/src/tool/twin-paradox-visualizer/i18n/ru.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/sv.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/tr.ts +168 -168
- package/src/tool/twin-paradox-visualizer/i18n/zh.ts +168 -168
- package/src/types.ts +1 -1
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
---
|
|
2
|
-
import { Icon } from "astro-icon/components";
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
ui: Record<string, string>;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const { ui } = Astro.props;
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
12
|
-
|
|
13
|
-
<div class="asteroid-app" id="asteroid-app">
|
|
14
|
-
<div id="asteroid-game-map" class="asteroid-game-map" style="touch-action: none;"></div>
|
|
15
|
-
|
|
16
|
-
<div id="asteroid-map-target-overlay" class="asteroid-map-target-overlay">
|
|
17
|
-
<div class="asteroid-target-crosshair"></div>
|
|
18
|
-
<div class="asteroid-target-crosshair vertical"></div>
|
|
19
|
-
<div class="asteroid-target-box"></div>
|
|
20
|
-
</div>
|
|
21
|
-
|
|
1
|
+
---
|
|
2
|
+
import { Icon } from "astro-icon/components";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
ui: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { ui } = Astro.props;
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
|
12
|
+
|
|
13
|
+
<div class="asteroid-app" id="asteroid-app">
|
|
14
|
+
<div id="asteroid-game-map" class="asteroid-game-map" style="touch-action: none;"></div>
|
|
15
|
+
|
|
16
|
+
<div id="asteroid-map-target-overlay" class="asteroid-map-target-overlay">
|
|
17
|
+
<div class="asteroid-target-crosshair"></div>
|
|
18
|
+
<div class="asteroid-target-crosshair vertical"></div>
|
|
19
|
+
<div class="asteroid-target-box"></div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
22
|
<div class="asteroid-top-bar">
|
|
23
23
|
<div>
|
|
24
24
|
<button id="asteroid-gps-btn" class="asteroid-gps-btn">
|
|
25
|
-
<div id="asteroid-gps-dot" class="asteroid-gps-dot"></div>
|
|
26
|
-
<span id="asteroid-gps-text">{ui.activateGPS}</span>
|
|
27
|
-
</button>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<div id="asteroid-verdict-pill" class="asteroid-verdict-pill">
|
|
31
|
-
<div id="asteroid-verdict-container" class="asteroid-verdict-container">
|
|
32
|
-
<div id="asteroid-verdict-icon" class="asteroid-verdict-icon"></div>
|
|
33
|
-
<div class="asteroid-verdict-text">
|
|
34
|
-
<div id="asteroid-verdict-label" class="asteroid-verdict-label">{ui.analysisLabel}</div>
|
|
35
|
-
<div id="asteroid-verdict-value" class="asteroid-verdict-value">--</div>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
25
|
+
<div id="asteroid-gps-dot" class="asteroid-gps-dot"></div>
|
|
26
|
+
<span id="asteroid-gps-text">{ui.activateGPS}</span>
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div id="asteroid-verdict-pill" class="asteroid-verdict-pill">
|
|
31
|
+
<div id="asteroid-verdict-container" class="asteroid-verdict-container">
|
|
32
|
+
<div id="asteroid-verdict-icon" class="asteroid-verdict-icon"></div>
|
|
33
|
+
<div class="asteroid-verdict-text">
|
|
34
|
+
<div id="asteroid-verdict-label" class="asteroid-verdict-label">{ui.analysisLabel}</div>
|
|
35
|
+
<div id="asteroid-verdict-value" class="asteroid-verdict-value">--</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
38
|
</div>
|
|
39
39
|
</div>
|
|
40
40
|
|
|
@@ -51,11 +51,11 @@ const { ui } = Astro.props;
|
|
|
51
51
|
<div class="asteroid-lab-title">
|
|
52
52
|
<div class="asteroid-lab-icon">
|
|
53
53
|
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
|
54
|
-
<path d="M12,2L11,7H13L12,2M6.5,5.27L5.77,6L9.5,9.73L10.23,9L6.5,5.27M17.5,5.27L13.77,9L14.5,9.73L18.23,6L17.5,5.27M2,11V13H7V11H2M17,11V13H22V11H17M9.5,14.27L5.77,18L6.5,18.73L10.23,15L9.5,14.27M14.5,14.27L13.77,15L17.5,18.73L18.23,18L14.5,14.27M11,17L12,22L13,17H11Z"></path>
|
|
55
|
-
</svg>
|
|
56
|
-
</div>
|
|
57
|
-
<div>
|
|
58
|
-
<h2 class="asteroid-lab-name">Asteroid</h2>
|
|
54
|
+
<path d="M12,2L11,7H13L12,2M6.5,5.27L5.77,6L9.5,9.73L10.23,9L6.5,5.27M17.5,5.27L13.77,9L14.5,9.73L18.23,6L17.5,5.27M2,11V13H7V11H2M17,11V13H22V11H17M9.5,14.27L5.77,18L6.5,18.73L10.23,15L9.5,14.27M14.5,14.27L13.77,15L17.5,18.73L18.23,18L14.5,14.27M11,17L12,22L13,17H11Z"></path>
|
|
55
|
+
</svg>
|
|
56
|
+
</div>
|
|
57
|
+
<div>
|
|
58
|
+
<h2 class="asteroid-lab-name">Asteroid</h2>
|
|
59
59
|
<span class="asteroid-lab-subtitle">Factory</span>
|
|
60
60
|
</div>
|
|
61
61
|
</div>
|
|
@@ -164,16 +164,16 @@ const { ui } = Astro.props;
|
|
|
164
164
|
<div id="icon-burn"><svg class="w-6 h-6" style="color: #fb923c;" fill="currentColor" viewBox="0 0 24 24"><path d="M17.66,11.2C17.43,10.9 17.15,10.64 16.89,10.38C16.22,9.78 15.46,9.35 14.82,8.72C13.33,7.26 13,4.85 13.95,3C13,3.23 12.17,3.75 11.46,4.32C8.87,6.4 7.85,10.07 9.07,13.22C9.11,13.32 9.15,13.42 9.15,13.55C9.15,13.77 9,13.97 8.8,14.05C8.57,14.15 8.33,14.09 8.14,13.93C8.08,13.88 8.04,13.83 8,13.76C6.87,12.33 6.69,10.28 7.45,8.64C5.78,10 4.87,12.3 5,14.47C5.06,14.97 5.12,15.47 5.29,15.97C5.43,16.57 5.7,17.17 6,17.7C7.08,19.43 8.95,20.67 10.96,20.92C13.1,21.19 15.39,20.8 17.03,19.32C18.86,17.66 19.5,15 18.56,12.72L18.43,12.46C18.22,12 17.66,11.2 17.66,11.2Z"></path></svg></div>
|
|
165
165
|
<div id="icon-death"><svg class="w-6 h-6" style="color: #f87171;" fill="currentColor" viewBox="0 0 24 24"><path d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z"></path></svg></div>
|
|
166
166
|
</div>
|
|
167
|
-
|
|
168
|
-
<script>
|
|
169
|
-
import L from "leaflet";
|
|
170
|
-
import { ImpactPhysics, type Composition } from "./logic/impactPhysics";
|
|
171
|
-
import { VERDICT_CONFIGS } from "./constants";
|
|
172
|
-
import { getCompositionColor } from "./utils";
|
|
173
|
-
import { updateControlUI } from "./ui-helpers";
|
|
174
|
-
|
|
175
|
-
let map: L.Map;
|
|
176
|
-
|
|
167
|
+
|
|
168
|
+
<script>
|
|
169
|
+
import L from "leaflet";
|
|
170
|
+
import { ImpactPhysics, type Composition } from "./logic/impactPhysics";
|
|
171
|
+
import { VERDICT_CONFIGS } from "./constants";
|
|
172
|
+
import { getCompositionColor } from "./utils";
|
|
173
|
+
import { updateControlUI } from "./ui-helpers";
|
|
174
|
+
|
|
175
|
+
let map: L.Map;
|
|
176
|
+
|
|
177
177
|
interface ImpactData { craterDiameter: number; thermalRadius: number; shockwave1psi: number; }
|
|
178
178
|
|
|
179
179
|
const impacts: { id: string; circles: L.LayerGroup; marker: L.Marker; data: ImpactData; latlng: L.LatLng; config: typeof config; }[] = [];
|
|
@@ -181,14 +181,14 @@ const { ui } = Astro.props;
|
|
|
181
181
|
let observerLatLng: L.LatLng, observerMarker: L.Marker;
|
|
182
182
|
|
|
183
183
|
const config = { diameter: 10000, velocity: 20, composition: "rock" as Composition };
|
|
184
|
-
|
|
185
|
-
function init() {
|
|
186
|
-
map = L.map("asteroid-game-map", {
|
|
187
|
-
zoomControl: false,
|
|
188
|
-
attributionControl: false,
|
|
189
|
-
dragging: true,
|
|
190
|
-
}).setView([40.4168, -3.7038], 6);
|
|
191
|
-
|
|
184
|
+
|
|
185
|
+
function init() {
|
|
186
|
+
map = L.map("asteroid-game-map", {
|
|
187
|
+
zoomControl: false,
|
|
188
|
+
attributionControl: false,
|
|
189
|
+
dragging: true,
|
|
190
|
+
}).setView([40.4168, -3.7038], 6);
|
|
191
|
+
|
|
192
192
|
L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.webp", {
|
|
193
193
|
subdomains: "abcd",
|
|
194
194
|
maxZoom: 20,
|
|
@@ -221,93 +221,93 @@ const { ui } = Astro.props;
|
|
|
221
221
|
close?.addEventListener("click", closeControls); backdrop?.addEventListener("click", closeControls);
|
|
222
222
|
dropCenterBtn?.addEventListener("click", () => { spawnImpact(map.getCenter()); closeControls(); });
|
|
223
223
|
}
|
|
224
|
-
|
|
225
|
-
function setupControls() {
|
|
226
|
-
const sizeInput = document.getElementById("input-size") as HTMLInputElement;
|
|
227
|
-
const velInput = document.getElementById("input-velocity") as HTMLInputElement;
|
|
228
|
-
const matBtns = document.querySelectorAll(".asteroid-material-btn");
|
|
229
|
-
const presetBtns = document.querySelectorAll(".asteroid-preset-btn");
|
|
230
|
-
const clearBtn = document.getElementById("clear-btn");
|
|
231
|
-
|
|
232
|
-
sizeInput?.addEventListener("input", (e) => {
|
|
233
|
-
config.diameter = parseInt((e.target as HTMLInputElement).value);
|
|
234
|
-
updateControlUI(config);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
velInput?.addEventListener("input", (e) => {
|
|
238
|
-
config.velocity = parseInt((e.target as HTMLInputElement).value);
|
|
239
|
-
updateControlUI(config);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
matBtns.forEach((btn) => {
|
|
243
|
-
btn.addEventListener("click", () => {
|
|
244
|
-
config.composition = btn.getAttribute("data-type") as Composition;
|
|
245
|
-
updateControlUI(config);
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
presetBtns.forEach((btn) => {
|
|
250
|
-
btn.addEventListener("click", () => {
|
|
251
|
-
config.diameter = parseInt(btn.getAttribute("data-dia")!);
|
|
252
|
-
config.velocity = parseInt(btn.getAttribute("data-vel")!);
|
|
253
|
-
config.composition = btn.getAttribute("data-comp") as Composition;
|
|
254
|
-
updateControlUI(config);
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
clearBtn?.addEventListener("click", clearAll);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function getEventCoordinates(e: MouseEvent | TouchEvent) {
|
|
262
|
-
const touch = (e as TouchEvent).changedTouches?.[0];
|
|
263
|
-
const clientX = (e as MouseEvent).clientX || touch?.clientX || 0;
|
|
264
|
-
const clientY = (e as MouseEvent).clientY || touch?.clientY || 0;
|
|
265
|
-
return { clientX, clientY };
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function setupGhostDrag() {
|
|
269
|
-
const source = document.getElementById("drag-source-desktop");
|
|
270
|
-
if (!source) return;
|
|
271
|
-
|
|
272
|
-
const start = (e: MouseEvent | TouchEvent) => {
|
|
273
|
-
e.preventDefault();
|
|
274
|
-
const targetOverlay = document.getElementById("asteroid-map-target-overlay");
|
|
275
|
-
if (targetOverlay) targetOverlay.classList.add("active");
|
|
276
|
-
|
|
277
|
-
const onMove = (moveEvent: MouseEvent | TouchEvent) => {
|
|
278
|
-
moveEvent.preventDefault();
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
const onEnd = (endEvent: MouseEvent | TouchEvent) => {
|
|
282
|
-
if (targetOverlay) targetOverlay.classList.remove("active");
|
|
283
|
-
|
|
284
|
-
const coords = getEventCoordinates(endEvent);
|
|
285
|
-
const point = map.mouseEventToContainerPoint(coords as MouseEvent);
|
|
286
|
-
const latlng = map.containerPointToLatLng(point);
|
|
287
|
-
spawnImpact(latlng);
|
|
288
|
-
|
|
289
|
-
window.removeEventListener("mousemove", onMove);
|
|
290
|
-
window.removeEventListener("mouseup", onEnd);
|
|
291
|
-
window.removeEventListener("touchmove", onMove);
|
|
292
|
-
window.removeEventListener("touchend", onEnd);
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
window.addEventListener("mousemove", onMove);
|
|
296
|
-
window.addEventListener("mouseup", onEnd);
|
|
297
|
-
window.addEventListener("touchmove", onMove, { passive: false });
|
|
298
|
-
window.addEventListener("touchend", onEnd);
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
source.addEventListener("mousedown", start);
|
|
302
|
-
source.addEventListener("touchstart", start);
|
|
303
|
-
}
|
|
304
|
-
|
|
224
|
+
|
|
225
|
+
function setupControls() {
|
|
226
|
+
const sizeInput = document.getElementById("input-size") as HTMLInputElement;
|
|
227
|
+
const velInput = document.getElementById("input-velocity") as HTMLInputElement;
|
|
228
|
+
const matBtns = document.querySelectorAll(".asteroid-material-btn");
|
|
229
|
+
const presetBtns = document.querySelectorAll(".asteroid-preset-btn");
|
|
230
|
+
const clearBtn = document.getElementById("clear-btn");
|
|
231
|
+
|
|
232
|
+
sizeInput?.addEventListener("input", (e) => {
|
|
233
|
+
config.diameter = parseInt((e.target as HTMLInputElement).value);
|
|
234
|
+
updateControlUI(config);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
velInput?.addEventListener("input", (e) => {
|
|
238
|
+
config.velocity = parseInt((e.target as HTMLInputElement).value);
|
|
239
|
+
updateControlUI(config);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
matBtns.forEach((btn) => {
|
|
243
|
+
btn.addEventListener("click", () => {
|
|
244
|
+
config.composition = btn.getAttribute("data-type") as Composition;
|
|
245
|
+
updateControlUI(config);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
presetBtns.forEach((btn) => {
|
|
250
|
+
btn.addEventListener("click", () => {
|
|
251
|
+
config.diameter = parseInt(btn.getAttribute("data-dia")!);
|
|
252
|
+
config.velocity = parseInt(btn.getAttribute("data-vel")!);
|
|
253
|
+
config.composition = btn.getAttribute("data-comp") as Composition;
|
|
254
|
+
updateControlUI(config);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
clearBtn?.addEventListener("click", clearAll);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function getEventCoordinates(e: MouseEvent | TouchEvent) {
|
|
262
|
+
const touch = (e as TouchEvent).changedTouches?.[0];
|
|
263
|
+
const clientX = (e as MouseEvent).clientX || touch?.clientX || 0;
|
|
264
|
+
const clientY = (e as MouseEvent).clientY || touch?.clientY || 0;
|
|
265
|
+
return { clientX, clientY };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function setupGhostDrag() {
|
|
269
|
+
const source = document.getElementById("drag-source-desktop");
|
|
270
|
+
if (!source) return;
|
|
271
|
+
|
|
272
|
+
const start = (e: MouseEvent | TouchEvent) => {
|
|
273
|
+
e.preventDefault();
|
|
274
|
+
const targetOverlay = document.getElementById("asteroid-map-target-overlay");
|
|
275
|
+
if (targetOverlay) targetOverlay.classList.add("active");
|
|
276
|
+
|
|
277
|
+
const onMove = (moveEvent: MouseEvent | TouchEvent) => {
|
|
278
|
+
moveEvent.preventDefault();
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const onEnd = (endEvent: MouseEvent | TouchEvent) => {
|
|
282
|
+
if (targetOverlay) targetOverlay.classList.remove("active");
|
|
283
|
+
|
|
284
|
+
const coords = getEventCoordinates(endEvent);
|
|
285
|
+
const point = map.mouseEventToContainerPoint(coords as MouseEvent);
|
|
286
|
+
const latlng = map.containerPointToLatLng(point);
|
|
287
|
+
spawnImpact(latlng);
|
|
288
|
+
|
|
289
|
+
window.removeEventListener("mousemove", onMove);
|
|
290
|
+
window.removeEventListener("mouseup", onEnd);
|
|
291
|
+
window.removeEventListener("touchmove", onMove);
|
|
292
|
+
window.removeEventListener("touchend", onEnd);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
window.addEventListener("mousemove", onMove);
|
|
296
|
+
window.addEventListener("mouseup", onEnd);
|
|
297
|
+
window.addEventListener("touchmove", onMove, { passive: false });
|
|
298
|
+
window.addEventListener("touchend", onEnd);
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
source.addEventListener("mousedown", start);
|
|
302
|
+
source.addEventListener("touchstart", start);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
305
|
function createMarkerIcon(color: string): L.DivIcon {
|
|
306
306
|
return L.divIcon({
|
|
307
|
-
className: "asteroid-marker",
|
|
308
|
-
iconSize: [32, 32],
|
|
309
|
-
iconAnchor: [16, 16],
|
|
310
|
-
html: `<div style="width: 2rem; height: 2rem; border-radius: 50%; background-color: ${color}; border: 2px solid white; box-shadow: 0 4px 8px rgba(0,0,0,0.2);"></div>`,
|
|
307
|
+
className: "asteroid-marker",
|
|
308
|
+
iconSize: [32, 32],
|
|
309
|
+
iconAnchor: [16, 16],
|
|
310
|
+
html: `<div style="width: 2rem; height: 2rem; border-radius: 50%; background-color: ${color}; border: 2px solid white; box-shadow: 0 4px 8px rgba(0,0,0,0.2);"></div>`,
|
|
311
311
|
});
|
|
312
312
|
}
|
|
313
313
|
|
|
@@ -319,20 +319,20 @@ const { ui } = Astro.props;
|
|
|
319
319
|
observerLatLng = latlng; if (observerMarker) observerMarker.setLatLng(latlng);
|
|
320
320
|
else observerMarker = L.marker(latlng, { icon: createObserverIcon(), zIndexOffset: 1000 }).addTo(map); updateVerdict();
|
|
321
321
|
}
|
|
322
|
-
|
|
322
|
+
|
|
323
323
|
function setupMarkerDragHandlers(marker: L.Marker, group: L.LayerGroup, physics: ImpactData) {
|
|
324
|
-
marker.on("dragstart", () => {
|
|
325
|
-
map.dragging.disable();
|
|
326
|
-
});
|
|
327
|
-
|
|
324
|
+
marker.on("dragstart", () => {
|
|
325
|
+
map.dragging.disable();
|
|
326
|
+
});
|
|
327
|
+
|
|
328
328
|
marker.on("drag", (e: L.LeafletEvent) => {
|
|
329
329
|
const newPos = (e.target as L.Marker).getLatLng();
|
|
330
330
|
const impact = impacts.find((item) => item.marker === marker); if (impact) impact.latlng = newPos;
|
|
331
331
|
group.clearLayers();
|
|
332
332
|
renderCircles(newPos, physics, group);
|
|
333
333
|
updateVerdict();
|
|
334
|
-
});
|
|
335
|
-
|
|
334
|
+
});
|
|
335
|
+
|
|
336
336
|
marker.on("dragend", (e: L.LeafletEvent) => {
|
|
337
337
|
map.dragging.enable();
|
|
338
338
|
const newPos = (e.target as L.Marker).getLatLng();
|
|
@@ -340,98 +340,98 @@ const { ui } = Astro.props;
|
|
|
340
340
|
group.clearLayers();
|
|
341
341
|
renderCircles(newPos, physics, group);
|
|
342
342
|
updateVerdict();
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
function spawnImpact(latlng: L.LatLng) {
|
|
347
|
-
const physics = ImpactPhysics.calculate({
|
|
348
|
-
diameter: config.diameter,
|
|
349
|
-
velocity: config.velocity * 1000,
|
|
350
|
-
composition: config.composition,
|
|
351
|
-
distance: 0,
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
const group = L.layerGroup();
|
|
355
|
-
addCircleLayers(latlng, physics, group);
|
|
356
|
-
group.addTo(map);
|
|
357
|
-
|
|
358
|
-
const markerColor = getCompositionColor(config.composition);
|
|
359
|
-
const marker = L.marker(latlng, {
|
|
360
|
-
draggable: true,
|
|
361
|
-
icon: createMarkerIcon(markerColor),
|
|
362
|
-
}).addTo(map);
|
|
363
|
-
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function spawnImpact(latlng: L.LatLng) {
|
|
347
|
+
const physics = ImpactPhysics.calculate({
|
|
348
|
+
diameter: config.diameter,
|
|
349
|
+
velocity: config.velocity * 1000,
|
|
350
|
+
composition: config.composition,
|
|
351
|
+
distance: 0,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
const group = L.layerGroup();
|
|
355
|
+
addCircleLayers(latlng, physics, group);
|
|
356
|
+
group.addTo(map);
|
|
357
|
+
|
|
358
|
+
const markerColor = getCompositionColor(config.composition);
|
|
359
|
+
const marker = L.marker(latlng, {
|
|
360
|
+
draggable: true,
|
|
361
|
+
icon: createMarkerIcon(markerColor),
|
|
362
|
+
}).addTo(map);
|
|
363
|
+
|
|
364
364
|
impacts.push({ id: Date.now().toString(), circles: group, marker, data: physics, latlng, config });
|
|
365
|
-
setupMarkerDragHandlers(marker, group, physics);
|
|
366
|
-
updateVerdict();
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function addCircleLayers(latlng: L.LatLng, physics: ImpactData, group: L.LayerGroup) {
|
|
370
|
-
L.circle(latlng, {
|
|
371
|
-
radius: physics.craterDiameter / 2,
|
|
372
|
-
color: "#ef4444",
|
|
373
|
-
fillColor: "#ef4444",
|
|
374
|
-
fillOpacity: 0.6,
|
|
375
|
-
weight: 0,
|
|
376
|
-
}).addTo(group);
|
|
377
|
-
|
|
378
|
-
L.circle(latlng, {
|
|
379
|
-
radius: physics.thermalRadius,
|
|
380
|
-
color: "#f97316",
|
|
381
|
-
fillColor: "#f97316",
|
|
382
|
-
fillOpacity: 0.15,
|
|
383
|
-
weight: 1,
|
|
384
|
-
dashArray: "5 5",
|
|
385
|
-
}).addTo(group);
|
|
386
|
-
|
|
387
|
-
L.circle(latlng, {
|
|
388
|
-
radius: physics.shockwave1psi,
|
|
389
|
-
color: "#3b82f6",
|
|
390
|
-
fillColor: "#3b82f6",
|
|
391
|
-
fillOpacity: 0.05,
|
|
392
|
-
weight: 1,
|
|
393
|
-
}).addTo(group);
|
|
394
|
-
}
|
|
395
|
-
|
|
365
|
+
setupMarkerDragHandlers(marker, group, physics);
|
|
366
|
+
updateVerdict();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function addCircleLayers(latlng: L.LatLng, physics: ImpactData, group: L.LayerGroup) {
|
|
370
|
+
L.circle(latlng, {
|
|
371
|
+
radius: physics.craterDiameter / 2,
|
|
372
|
+
color: "#ef4444",
|
|
373
|
+
fillColor: "#ef4444",
|
|
374
|
+
fillOpacity: 0.6,
|
|
375
|
+
weight: 0,
|
|
376
|
+
}).addTo(group);
|
|
377
|
+
|
|
378
|
+
L.circle(latlng, {
|
|
379
|
+
radius: physics.thermalRadius,
|
|
380
|
+
color: "#f97316",
|
|
381
|
+
fillColor: "#f97316",
|
|
382
|
+
fillOpacity: 0.15,
|
|
383
|
+
weight: 1,
|
|
384
|
+
dashArray: "5 5",
|
|
385
|
+
}).addTo(group);
|
|
386
|
+
|
|
387
|
+
L.circle(latlng, {
|
|
388
|
+
radius: physics.shockwave1psi,
|
|
389
|
+
color: "#3b82f6",
|
|
390
|
+
fillColor: "#3b82f6",
|
|
391
|
+
fillOpacity: 0.05,
|
|
392
|
+
weight: 1,
|
|
393
|
+
}).addTo(group);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
396
|
function renderCircles(latlng: L.LatLng, physics: ImpactData, group: L.LayerGroup) { addCircleLayers(latlng, physics, group); }
|
|
397
|
-
|
|
398
|
-
function setupGPS() {
|
|
399
|
-
const btn = document.getElementById("asteroid-gps-btn");
|
|
400
|
-
btn?.addEventListener("click", () => {
|
|
401
|
-
const gpsText = document.getElementById("asteroid-gps-text");
|
|
402
|
-
if (gpsText) gpsText.textContent = "Buscando...";
|
|
403
|
-
|
|
404
|
-
navigator.geolocation.getCurrentPosition(
|
|
397
|
+
|
|
398
|
+
function setupGPS() {
|
|
399
|
+
const btn = document.getElementById("asteroid-gps-btn");
|
|
400
|
+
btn?.addEventListener("click", () => {
|
|
401
|
+
const gpsText = document.getElementById("asteroid-gps-text");
|
|
402
|
+
if (gpsText) gpsText.textContent = "Buscando...";
|
|
403
|
+
|
|
404
|
+
navigator.geolocation.getCurrentPosition(
|
|
405
405
|
(pos) => {
|
|
406
406
|
const ll = new L.LatLng(pos.coords.latitude, pos.coords.longitude);
|
|
407
407
|
setObserver(ll);
|
|
408
408
|
if (gpsText) gpsText.textContent = "GPS Activo";
|
|
409
409
|
map.flyTo(ll, 9);
|
|
410
410
|
},
|
|
411
|
-
() => {
|
|
412
|
-
if (gpsText) gpsText.textContent = "Error GPS";
|
|
413
|
-
}
|
|
414
|
-
);
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function updateVerdictUI(verdict: string) {
|
|
419
|
-
const label = document.getElementById("asteroid-verdict-label");
|
|
420
|
-
const value = document.getElementById("asteroid-verdict-value");
|
|
421
|
-
const icon = document.getElementById("asteroid-verdict-icon");
|
|
422
|
-
const container = document.getElementById("asteroid-verdict-container");
|
|
423
|
-
|
|
424
|
-
const c = VERDICT_CONFIGS[verdict];
|
|
425
|
-
if (c) {
|
|
426
|
-
if (value) value.textContent = c.text;
|
|
427
|
-
if (label) label.textContent = c.label;
|
|
428
|
-
if (container) container.className = `asteroid-verdict-container ${c.class}`;
|
|
429
|
-
|
|
430
|
-
const iconSource = document.getElementById(c.iconId);
|
|
431
|
-
if (icon && iconSource) icon.innerHTML = iconSource.innerHTML;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
411
|
+
() => {
|
|
412
|
+
if (gpsText) gpsText.textContent = "Error GPS";
|
|
413
|
+
}
|
|
414
|
+
);
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function updateVerdictUI(verdict: string) {
|
|
419
|
+
const label = document.getElementById("asteroid-verdict-label");
|
|
420
|
+
const value = document.getElementById("asteroid-verdict-value");
|
|
421
|
+
const icon = document.getElementById("asteroid-verdict-icon");
|
|
422
|
+
const container = document.getElementById("asteroid-verdict-container");
|
|
423
|
+
|
|
424
|
+
const c = VERDICT_CONFIGS[verdict];
|
|
425
|
+
if (c) {
|
|
426
|
+
if (value) value.textContent = c.text;
|
|
427
|
+
if (label) label.textContent = c.label;
|
|
428
|
+
if (container) container.className = `asteroid-verdict-container ${c.class}`;
|
|
429
|
+
|
|
430
|
+
const iconSource = document.getElementById(c.iconId);
|
|
431
|
+
if (icon && iconSource) icon.innerHTML = iconSource.innerHTML;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
435
|
function updateVerdict() {
|
|
436
436
|
const pill = document.getElementById("asteroid-verdict-pill");
|
|
437
437
|
if (impacts.length === 0) { pill?.classList.remove("active"); return; }
|
|
@@ -449,21 +449,21 @@ const { ui } = Astro.props;
|
|
|
449
449
|
return severity[verdict] > severity[worst] ? verdict : worst;
|
|
450
450
|
}, "safe");
|
|
451
451
|
}
|
|
452
|
-
|
|
453
|
-
function clearAll() {
|
|
454
|
-
impacts.forEach((i) => {
|
|
455
|
-
map.removeLayer(i.circles);
|
|
456
|
-
map.removeLayer(i.marker);
|
|
457
|
-
});
|
|
458
|
-
impacts.length = 0;
|
|
459
|
-
updateVerdict();
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
if (document.readyState === "loading") {
|
|
463
|
-
document.addEventListener("DOMContentLoaded", init);
|
|
464
|
-
} else {
|
|
465
|
-
init();
|
|
466
|
-
}
|
|
467
|
-
</script>
|
|
468
|
-
|
|
469
|
-
|
|
452
|
+
|
|
453
|
+
function clearAll() {
|
|
454
|
+
impacts.forEach((i) => {
|
|
455
|
+
map.removeLayer(i.circles);
|
|
456
|
+
map.removeLayer(i.marker);
|
|
457
|
+
});
|
|
458
|
+
impacts.length = 0;
|
|
459
|
+
updateVerdict();
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (document.readyState === "loading") {
|
|
463
|
+
document.addEventListener("DOMContentLoaded", init);
|
|
464
|
+
} else {
|
|
465
|
+
init();
|
|
466
|
+
}
|
|
467
|
+
</script>
|
|
468
|
+
|
|
469
|
+
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { type Composition } from "./logic/impactPhysics";
|
|
2
|
-
|
|
3
|
-
export function formatSize(diameter: number): string {
|
|
4
|
-
return diameter >= 1000 ? `${(diameter / 1000).toFixed(1)} km` : `${diameter}m`;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function getTypeLabel(composition: Composition): string {
|
|
8
|
-
if (composition === "ice") return "Hielo";
|
|
9
|
-
if (composition === "iron") return "Hierro";
|
|
10
|
-
return "Roca";
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function getCompositionColor(composition: Composition): string {
|
|
14
|
-
if (composition === "ice") return "#67e8f9";
|
|
15
|
-
if (composition === "iron") return "#1e293b";
|
|
16
|
-
return "#64748b";
|
|
17
|
-
}
|
|
1
|
+
import { type Composition } from "./logic/impactPhysics";
|
|
2
|
+
|
|
3
|
+
export function formatSize(diameter: number): string {
|
|
4
|
+
return diameter >= 1000 ? `${(diameter / 1000).toFixed(1)} km` : `${diameter}m`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getTypeLabel(composition: Composition): string {
|
|
8
|
+
if (composition === "ice") return "Hielo";
|
|
9
|
+
if (composition === "iron") return "Hierro";
|
|
10
|
+
return "Roca";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getCompositionColor(composition: Composition): string {
|
|
14
|
+
if (composition === "ice") return "#67e8f9";
|
|
15
|
+
if (composition === "iron") return "#1e293b";
|
|
16
|
+
return "#64748b";
|
|
17
|
+
}
|