mirror of
https://github.com/its-michaelroy/Deep-Impact.git
synced 2026-06-04 02:20:41 +00:00
Merge pull request #13 from Team-Deep-Impact/dev
Day 2 latest complete work
This commit is contained in:
82
README.md
82
README.md
@@ -1,3 +1,83 @@
|
|||||||
# Deep Impact
|
# Deep Impact
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Deep Impact is a web application designed to provide users with insights into the potential dangers of asteroid impacts. Utilizing the NASA NeoWs API, we've developed a simulation tool that visualizes incoming asteroids and explores various methods of asteroid deflection.
|
||||||
|
|
||||||
|
### Our Team
|
||||||
|
|
||||||
|
- Daniel Smith-dePaz
|
||||||
|
- Jordan Yamada
|
||||||
|
- Pierre Bell
|
||||||
|
- Michael Roy
|
||||||
|
- Mickey Shoenberger
|
||||||
|
- Jordan Edgington
|
||||||
|
|
||||||
|
To learn more about Deep Impact, check out our [Deep Impact GitHub](https://github.com/Team-Deep-Impact/Deep-Impact).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
1. **Asteroid Visualization**: Visualize incoming asteroids using real-time data from the NASA NeoWs API.
|
||||||
|
2. **Scenario & Deflection Strategies**: Explore various methods of asteroid deflection, such as Nuclear Detonation, Kinetic Impact, and Gravity Tractor.
|
||||||
|
3. **Simulation Tool**: Simulate asteroid trajectories and deflection outcomes.
|
||||||
|
4. **Dashboard**: View the dashboard, and other pages with relevant information and insights.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Django Backend Setup
|
||||||
|
|
||||||
|
1. **Set Up Python Environment**:
|
||||||
|
- Vanilla Python:
|
||||||
|
```sh
|
||||||
|
python -m venv .venv
|
||||||
|
```
|
||||||
|
- Virtual Environment Wrapper:
|
||||||
|
```sh
|
||||||
|
mkvirtualenv .venv
|
||||||
|
```
|
||||||
|
- Activate the environment:
|
||||||
|
```sh
|
||||||
|
source .venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Install Required Packages**:
|
||||||
|
- Navigate to the backend directory and install dependencies:
|
||||||
|
```sh
|
||||||
|
cd Deep-Impact/backend
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Initial Migration(s)**:
|
||||||
|
- Ensure you're located in the path: Deep-Impact/backend
|
||||||
|
```sh
|
||||||
|
python manage.py makemigrations
|
||||||
|
python manage.py migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Start Django Server**:
|
||||||
|
- Ensure you're located in the path: Deep-Impact/backend
|
||||||
|
```sh
|
||||||
|
python manage.py runserver
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vite Frontend Setup
|
||||||
|
|
||||||
|
1. **Install Node Modules**:
|
||||||
|
- Navigate to the frontend directory and install dependencies:
|
||||||
|
```sh
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Run Development Server**:
|
||||||
|
- Start the development server:
|
||||||
|
```sh
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Deep Impact is open-source software released under the [MIT License](LICENSE). Feel free to use, modify, and distribute the codebase in accordance with the terms of the license.
|
||||||
|
|
||||||
|
Thank you for choosing Deep Impact. We hope you enjoy exploring our project and learning more about asteroid impacts!
|
||||||
|
|||||||
6
backend/.env.sample
Normal file
6
backend/.env.sample
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
SECRET_KEY=<"Your Django Secret Key">
|
||||||
|
SENTRY_API_KEY=<"Your NASA Sentry API Key">
|
||||||
|
OPENAI_API_KEY=<"Your OpenAI API Key">
|
||||||
|
HOST_CLIENT=<"Your FrontEnd URL">
|
||||||
|
ALLOWED_HOSTS=<"Your Server URL">
|
||||||
|
DEBUG=<"True for Deployment | False for Development">
|
||||||
3
backend/.gitignore
vendored
Normal file
3
backend/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.env
|
||||||
|
.venv
|
||||||
|
/__pycache__/
|
||||||
0
backend/api_app/__init__.py
Normal file
0
backend/api_app/__init__.py
Normal file
3
backend/api_app/admin.py
Normal file
3
backend/api_app/admin.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
6
backend/api_app/apps.py
Normal file
6
backend/api_app/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ApiAppConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'api_app'
|
||||||
0
backend/api_app/migrations/__init__.py
Normal file
0
backend/api_app/migrations/__init__.py
Normal file
3
backend/api_app/models.py
Normal file
3
backend/api_app/models.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
3
backend/api_app/tests.py
Normal file
3
backend/api_app/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
9
backend/api_app/urls.py
Normal file
9
backend/api_app/urls.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from django.urls import path
|
||||||
|
from .views import Sentry, OpenAI
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('sentry/', Sentry.as_view(), name='sentry'),
|
||||||
|
path('openai/', OpenAI.as_view(), name='openai'),
|
||||||
|
]
|
||||||
23
backend/api_app/utils.py
Normal file
23
backend/api_app/utils.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.status import (
|
||||||
|
HTTP_200_OK,
|
||||||
|
HTTP_204_NO_CONTENT,
|
||||||
|
HTTP_201_CREATED,
|
||||||
|
HTTP_400_BAD_REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
sentry_api_key = os.environ.get("SENTRY_API_KEY")
|
||||||
|
|
||||||
|
def get_sentry():
|
||||||
|
try:
|
||||||
|
response = requests.get(f'https://api.nasa.gov/neo/rest/v1/neo/browse?api_key={sentry_api_key}')
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
return Response(data, status=HTTP_200_OK)
|
||||||
|
except ValidationError as e:
|
||||||
|
print(e)
|
||||||
|
return Response(e, status=HTTP_400_BAD_REQUEST)
|
||||||
26
backend/api_app/views.py
Normal file
26
backend/api_app/views.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.status import (
|
||||||
|
HTTP_200_OK,
|
||||||
|
HTTP_204_NO_CONTENT,
|
||||||
|
HTTP_201_CREATED,
|
||||||
|
HTTP_400_BAD_REQUEST
|
||||||
|
)
|
||||||
|
from .utils import get_sentry
|
||||||
|
|
||||||
|
sentry_api_key = os.environ.get("SENTRY_API_KEY")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
|
class Sentry(APIView):
|
||||||
|
def get(self, request):
|
||||||
|
return get_sentry()
|
||||||
|
|
||||||
|
|
||||||
|
class OpenAI(APIView):
|
||||||
|
pass
|
||||||
BIN
backend/db.sqlite3
Normal file
BIN
backend/db.sqlite3
Normal file
Binary file not shown.
0
backend/deep_impact_proj/__init__.py
Normal file
0
backend/deep_impact_proj/__init__.py
Normal file
16
backend/deep_impact_proj/asgi.py
Normal file
16
backend/deep_impact_proj/asgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for deep_impact_proj project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'deep_impact_proj.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
||||||
138
backend/deep_impact_proj/settings.py
Normal file
138
backend/deep_impact_proj/settings.py
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
"""
|
||||||
|
Django settings for deep_impact_proj project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 5.0.4.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.0/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/5.0/ref/settings/
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Load environment variables from .env file
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = os.environ.get("SECRET_KEY")
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = os.environ.get("DEBUG")
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = [os.environ.get("ALLOWED_HOSTS"), "localhost"]
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'corsheaders',
|
||||||
|
'api_app',
|
||||||
|
'rest_framework',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'corsheaders.middleware.CorsMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'deep_impact_proj.urls'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CORS_ALLOWED_ORIGINS = [os.environ.get("HOST_CLIENT")]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'deep_impact_proj.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/5.0/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/5.0/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
23
backend/deep_impact_proj/urls.py
Normal file
23
backend/deep_impact_proj/urls.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
"""
|
||||||
|
URL configuration for deep_impact_proj project.
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/5.0/topics/http/urls/
|
||||||
|
Examples:
|
||||||
|
Function views
|
||||||
|
1. Add an import: from my_app import views
|
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||||
|
Class-based views
|
||||||
|
1. Add an import: from other_app.views import Home
|
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||||
|
Including another URLconf
|
||||||
|
1. Import the include() function: from django.urls import include, path
|
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
|
"""
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path, include
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
path('api/', include('api_app.urls')),
|
||||||
|
]
|
||||||
16
backend/deep_impact_proj/wsgi.py
Normal file
16
backend/deep_impact_proj/wsgi.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for deep_impact_proj project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'deep_impact_proj.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
||||||
22
backend/manage.py
Executable file
22
backend/manage.py
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'deep_impact_proj.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
17
backend/requirements.txt
Normal file
17
backend/requirements.txt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
asgiref==3.8.1
|
||||||
|
certifi==2024.2.2
|
||||||
|
charset-normalizer==3.3.2
|
||||||
|
click==8.1.7
|
||||||
|
Django==5.0.6
|
||||||
|
django-cors-headers==4.2.0
|
||||||
|
djangorestframework==3.15.1
|
||||||
|
gunicorn==22.0.0
|
||||||
|
h11==0.14.0
|
||||||
|
idna==3.7
|
||||||
|
packaging==24.0
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
requests==2.31.0
|
||||||
|
sqlparse==0.5.0
|
||||||
|
urllib3==2.2.1
|
||||||
|
uvicorn==0.29.0
|
||||||
|
whitenoise==6.6.0
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/" href="/DeepImpact_Logo.jpeg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + React</title>
|
<title>Deep Impact</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
841
frontend/package-lock.json
generated
841
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,15 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.11.4",
|
||||||
|
"@emotion/styled": "^11.11.5",
|
||||||
|
"@mui/material": "^5.15.18",
|
||||||
|
"axios": "^1.6.8",
|
||||||
|
"konva": "^9.3.8",
|
||||||
|
"nvm": "^0.0.4",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-konva": "^18.2.10",
|
||||||
"react-router-dom": "^6.23.1"
|
"react-router-dom": "^6.23.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -25,6 +32,6 @@
|
|||||||
"eslint-plugin-react-refresh": "^0.4.6",
|
"eslint-plugin-react-refresh": "^0.4.6",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
"vite": "^5.2.0"
|
"vite": "^5.2.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
frontend/public/DeepImpact.png
Normal file
BIN
frontend/public/DeepImpact.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
BIN
frontend/public/DeepImpact_Logo.jpeg
Normal file
BIN
frontend/public/DeepImpact_Logo.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 217 KiB |
BIN
frontend/src/assets/Objects_between_earth_and_moon.jpg
Normal file
BIN
frontend/src/assets/Objects_between_earth_and_moon.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
frontend/src/assets/Objects_between_earth_and_moon_crop.jpg
Normal file
BIN
frontend/src/assets/Objects_between_earth_and_moon_crop.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 278 KiB |
@@ -9,6 +9,8 @@ function NavBar() {
|
|||||||
<li><Link to='/'><p className='text-2xl text-white hover:text-red-900'>Main</p></Link></li>
|
<li><Link to='/'><p className='text-2xl text-white hover:text-red-900'>Main</p></Link></li>
|
||||||
<li><Link to='scenario/'><p className='text-2xl text-white hover:text-red-900'>Scenario</p></Link></li>
|
<li><Link to='scenario/'><p className='text-2xl text-white hover:text-red-900'>Scenario</p></Link></li>
|
||||||
<li><Link to='about/'><p className='text-2xl text-white hover:text-red-900'>About</p></Link></li>
|
<li><Link to='about/'><p className='text-2xl text-white hover:text-red-900'>About</p></Link></li>
|
||||||
|
<li><Link to='effects/'><p className='text-2xl text-white hover:text-red-900'>Effects</p></Link></li>
|
||||||
|
<li><Link to='defenses/'><p className='text-2xl text-white hover:text-red-900'>Defenses</p></Link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -2,12 +2,27 @@ function About() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div className='text-white text-center flex flex-col w-1/2'>
|
||||||
<p>About</p>
|
<div className='m-4'>
|
||||||
|
<p className='text-2xl underline mb-2'>What is Deep Impact?</p>
|
||||||
|
<p>Deep impact is a web-app designed to give users insight into potential danger of asteroid impact. Using the NASA NeoWs API we have created a simulation tool to visualize incoming asteroids and various methods of asteroid deflection.</p>
|
||||||
|
</div>
|
||||||
|
<div className='m-4'>
|
||||||
|
<p className='text-2xl underline mb-2'>Our Team</p>
|
||||||
|
<ul>
|
||||||
|
<li>Daniel Smith-dePaz</li>
|
||||||
|
<li>Jordan Yamada</li>
|
||||||
|
<li>Pierre Bell</li>
|
||||||
|
<li>Michael Roy</li>
|
||||||
|
<li>Mickey Shoenberger</li>
|
||||||
|
<li>Jordan Edgington</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<p className='italic m-4'>The Sky Is Falling!</p>
|
||||||
|
<p className='m-4'>To see learn more about Deep Impact, checkout our <a href='https://github.com/Team-Deep-Impact/Deep-Impact' className='underline hover:text-red-900'>GitHub</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default About
|
export default About
|
||||||
|
|
||||||
117
frontend/src/pages/defenses.jsx
Normal file
117
frontend/src/pages/defenses.jsx
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
const Defenses = () => {
|
||||||
|
return (
|
||||||
|
<div className="w-8/12 mx-auto">
|
||||||
|
<h1 className="text-center text-2xl text-white my-5">Defensive Options</h1>
|
||||||
|
<h2 className="text-center underline text-xl text-white my-5">What Can We Do?</h2>
|
||||||
|
<p className="text-l text-white">
|
||||||
|
Defending Earth against potentially hazardous meteors or asteroids involves several strategies and technologies, primarily focused on detection, deflection, and disruption. Here are the primary defense options:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Early Detection and Monitoring</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Space-Based Telescopes:</strong> Deploying telescopes in space to continuously monitor the sky for Near-Earth Objects (NEOs). Examples include NASA’s NEOWISE mission and the upcoming NEOCam.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Ground-Based Telescopes:</strong> Utilizing a network of observatories around the world to detect and track asteroids. Projects like the Pan-STARRS and the Catalina Sky Survey are part of this effort.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Data Sharing and Coordination:</strong> International collaboration through organizations like the International Asteroid Warning Network (IAWN) and the Space Mission Planning Advisory Group (SMPAG) to share data and coordinate responses.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Deflection Techniques</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Kinetic Impactor:</strong> This involves sending a spacecraft to collide with the asteroid at high speed, changing its trajectory. NASA’s Double Asteroid Redirection Test (DART) mission is an example, scheduled to test this method on the moonlet of the asteroid Didymos.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Gravity Tractor:</strong> A spacecraft would fly alongside the asteroid for an extended period, using its gravitational pull to gradually alter the asteroid’s path.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Ion Beam Shepherd:</strong> This concept involves using ion thrusters to create a continuous stream of particles that push against the asteroid, slowly changing its trajectory over time.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Disruption Techniques</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Nuclear Explosions:</strong> A nuclear device could be detonated near or on the asteroid to either vaporize a portion of it or to alter its course significantly. This is considered a last resort due to the potential for fragmenting the asteroid into multiple pieces, which might still pose a threat.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Laser Ablation:</strong> Using high-powered lasers to vaporize the surface of the asteroid, creating jets of gas that would act as a propulsion mechanism to nudge the asteroid off course.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Civil Protection and Mitigation</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Impact Prediction and Modeling:</strong> Improved computer models to predict impact locations, potential damage, and secondary effects like tsunamis and atmospheric changes.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Evacuation Plans:</strong> Developing and rehearsing evacuation plans for regions identified as potential impact sites.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Global Response Coordination:</strong> Establishing international protocols for disaster response, resource distribution, and public communication.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">General Effects on Human Civilization</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Economic Disruption:</strong> Severe damage to infrastructure, agriculture, and resources can lead to economic collapse in affected regions.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Human Casualties:</strong> Direct impact areas would suffer heavy casualties, with potential global consequences from secondary effects like famine and disease.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Global Cooperation and Response:</strong> Such an event would likely necessitate global cooperation for disaster response, food distribution, and potentially relocation of populations.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">International Collaboration and Policy Development</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Space Treaties and Agreements:</strong> Strengthening international treaties and agreements to ensure cooperation and shared responsibility in asteroid detection and deflection efforts.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Funding and Research:</strong> Increasing funding for asteroid research, detection programs, and the development of deflection technologies.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Key Missions and Programs</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>NASA’s Planetary Defense Coordination Office (PDCO):</strong> Coordinates efforts to detect, track, and characterize potentially hazardous asteroids and comets.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>ESA’s Hera Mission:</strong> A follow-up to NASA’s DART mission, Hera will study the aftermath of the DART impact to gather critical data on the effectiveness of kinetic impactors.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Space Situational Awareness (SSA) Program:</strong> Run by the European Space Agency (ESA) to detect and track objects that pose a risk to Earth or to satellites in orbit.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Challenges and Considerations</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Timely Detection:</strong> Early detection is crucial, as deflection methods are more effective when applied well in advance of a potential impact.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Technological Development:</strong> Many of the proposed deflection techniques are still in the research or testing phase and require further development.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>International Cooperation:</strong> Effective planetary defense requires global collaboration, as the impact of a large asteroid would have worldwide consequences.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="mt-3">
|
||||||
|
<p className="text-l text-white mb-10">
|
||||||
|
By combining these strategies, the global community aims to protect Earth from the potentially devastating effects of asteroid impacts.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Defenses;
|
||||||
94
frontend/src/pages/effects.jsx
Normal file
94
frontend/src/pages/effects.jsx
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
const Effects = () => {
|
||||||
|
return (
|
||||||
|
<div className="w-8/12 mx-auto">
|
||||||
|
<h1 className="text-center text-2xl text-white my-5">Effects of an Impact</h1>
|
||||||
|
<h2 className="text-center underline text-xl text-white my-5">The Impact of a Meteor Hitting Earth</h2>
|
||||||
|
<p className="text-l text-white">
|
||||||
|
The impact of a meteor hitting Earth can vary widely depending on the size, composition, speed, and location of the impact. Here are the key impacts based on the size of the meteor:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Small Meteors (up to 25 meters in diameter)</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Atmospheric Entry:</strong> These meteors typically burn up upon entering the Earth’s atmosphere, causing a bright flash and potentially a sonic boom.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Damage:</strong> If fragments reach the ground, they may cause minor damage locally, such as breaking windows or small craters. An example is the Chelyabinsk meteor in 2013, which caused injuries mainly from broken glass.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Medium Meteors (25 meters to 1 kilometer in diameter)</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Local Destruction:</strong> A meteor in this size range can cause significant local destruction, including fires, shockwaves, and substantial craters.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Tsunamis:</strong> If it impacts an ocean, it can generate large tsunamis capable of affecting coastal areas over a wide region.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Climate Effects:</strong> Dust and debris thrown into the atmosphere can lead to short-term climate changes, such as “impact winter,” where sunlight is blocked, leading to global cooling and agricultural impacts.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Large Meteors (1 kilometer to 10 kilometers in diameter)</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Regional to Global Catastrophe:</strong> These impacts can cause massive destruction over hundreds of kilometers from the impact site. The blast, heat, and shockwave can annihilate life forms in the vicinity.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Tsunamis:</strong> If the impact occurs in the ocean, it would generate massive tsunamis with potentially devastating global effects on coastal regions.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Climate Disruption:</strong> The impact would throw vast amounts of dust, ash, and aerosols into the atmosphere, potentially causing global cooling for years. This can disrupt ecosystems, agriculture, and food supplies globally.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Extinctions:</strong> Such an event can lead to mass extinctions due to the combination of immediate destruction, climatic effects, and ecological collapse. The most well-known example is the Chicxulub impactor, which contributed to the extinction of the dinosaurs 66 million years ago.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Very Large Meteors (over 10 kilometers in diameter)</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Global Catastrophe:</strong> These are extremely rare but can cause near-instantaneous global devastation.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Immediate Effects:</strong> Massive firestorms, shockwaves, and tsunamis would affect the entire planet.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Long-term Effects:</strong> Severe climate changes, including extended “impact winters,” leading to mass extinctions and potentially the collapse of human civilization.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">General Effects on Human Civilization</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Economic Disruption:</strong> Severe damage to infrastructure, agriculture, and resources can lead to economic collapse in affected regions.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Human Casualties:</strong> Direct impact areas would suffer heavy casualties, with potential global consequences from secondary effects like famine and disease.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Global Cooperation and Response:</strong> Such an event would likely necessitate global cooperation for disaster response, food distribution, and potentially relocation of populations.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">Mitigation and Prevention</h3>
|
||||||
|
<ul className="list-disc pl-5 text-l text-white">
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Early Detection:</strong> Advances in space observation aim to detect potential impactors well in advance. Programs like NASA’s Near-Earth Object (NEO) Observations Program work towards this goal.
|
||||||
|
</li>
|
||||||
|
<li className="mb-3">
|
||||||
|
<strong>Deflection Strategies:</strong> Potential strategies for deflecting an asteroid include kinetic impactors, gravitational tractors, or even nuclear devices to alter the asteroid’s trajectory.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="mt-3">
|
||||||
|
<p className="text-l text-white mb-10">
|
||||||
|
In summary, while the impact of small meteors is relatively minor and localized, large meteors can have devastating global consequences. Preparedness and mitigation strategies are essential for minimizing the potential impacts of such events.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Effects;
|
||||||
@@ -1,13 +1,32 @@
|
|||||||
|
import distanceImage from '../assets/Objects_between_earth_and_moon_crop.jpg';
|
||||||
|
|
||||||
function Main() {
|
function Main() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div className='w-8/12 mx-auto'>
|
||||||
<p>Main</p>
|
<h1 className="text-center text-2xl text-white my-5">Welcome to Deep Impact!</h1>
|
||||||
|
<h2 className="text-center underline text-xl text-white my-5">Close Approaches</h2>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">How close?</h3>
|
||||||
|
<p className="text-l text-white">A body in space is considered a near-earth object if passing within 1.3 times the distance from the Earth to the Sun (defined as 1 astronomical unit, AU). For reference, the Earth is 93 million miles from the Sun (150 million km), and the moon is 238,900 miles (384,000 km) from Earth.</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">What's the issue?</h3>
|
||||||
|
<p className="text-l text-white">Collision with the earth can have significant effects on the environment, ranging from local effects to global impact.</p>
|
||||||
|
<p className="text-l text-white">A potential hazardous asteroid (PHA) would approach closer than 0.05 AU and a diameter of greater than 500 ft (140m).</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-bold text-white my-5">How often?</h3>
|
||||||
|
<p className="text-l text-white">Since 1900, NASA has logged 2,586 PHAs and anticipate 3,317 more out to 2200 AD.</p>
|
||||||
|
<img src={distanceImage} className="mt-5"/>
|
||||||
|
<p className="text-base text-white text-center">Comparison of the distances of satellite range and the closest approaches to the Earth</p>
|
||||||
|
|
||||||
|
<h2 className="text-center underline text-xl text-white my-5">Examples</h2>
|
||||||
|
<p className="text-l text-white">In 1957, 2019 CD2 asteroid passed 46,349 mi from Earth, with a diameter of 850-1940 ft. This is relatively large, and with this asteroid's orbit around the sun it will have at least 5 more close approaches in the future (although not as close).</p>
|
||||||
|
<p className="text-l text-white">In 2029, 99942 Apophis, an asteroid of around 1,115 ft in diameter, will pass 23,619 mi from the Earth.</p>
|
||||||
|
<p className="text-l text-white mb-10">The near-earth object everyone recognizes is Halley's Comet. With observations going back 2,000 years, the comet approaches the earth every 76 years. The comet is large, being about 48,000 ft by 26,000 ft. Thankfully the closest approach has been 0.033 AU (3 million miles), in 837 AD.</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Main
|
|
||||||
|
|
||||||
|
export default Main
|
||||||
|
|||||||
@@ -1,13 +1,358 @@
|
|||||||
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
|
import { Stage, Layer, Circle, Text, Line } from 'react-konva';
|
||||||
|
import { Slider, Button, MenuItem, Select, Typography, Box } from '@mui/material';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const EARTH_RADIUS_KM = 6371; // Earth's radius in kilometers
|
||||||
|
const EARTH_DISPLAY_SCALE = 0.01; // Display scale for Earth
|
||||||
|
const ASTEROID_DISPLAY_SCALE = 0.3; // Display scale for asteroids
|
||||||
|
const G = 1e-8; // Gravitational constant for simulation
|
||||||
|
const EARTH_MASS = 5.972e6; // Scaled down mass of Earth for simulation
|
||||||
|
const ASTEROID_DENSITY = 2000; // Density in kg/m^3
|
||||||
|
|
||||||
|
const CANVAS_WIDTH = window.innerWidth;
|
||||||
|
const CANVAS_HEIGHT = window.innerHeight;
|
||||||
|
const EARTH_X = CANVAS_WIDTH - 100;
|
||||||
|
const EARTH_Y = CANVAS_HEIGHT / 2;
|
||||||
|
const SIMULATION_AREA_MULTIPLIER = 2; // Extend the simulation area
|
||||||
|
const ROCKET_SPEED = 0.025; // Reduced speed of the rocket
|
||||||
|
|
||||||
function Scenario() {
|
function Scenario() {
|
||||||
|
const [asteroid, setAsteroid] = useState({
|
||||||
|
name: '',
|
||||||
|
size: 1,
|
||||||
|
speed: 0.05,
|
||||||
|
mass: 1,
|
||||||
|
angle: Math.PI / 9,
|
||||||
|
x: 100,
|
||||||
|
y: CANVAS_HEIGHT / 2 - 100,
|
||||||
|
});
|
||||||
|
const [trajectoryPoints, setTrajectoryPoints] = useState([]);
|
||||||
|
const [forecastPoints, setForecastPoints] = useState([]);
|
||||||
|
const animationRef = useRef();
|
||||||
|
const asteroidsData = useRef([]);
|
||||||
|
const [isSimulating, setIsSimulating] = useState(false);
|
||||||
|
const [simulationResult, setSimulationResult] = useState('');
|
||||||
|
const [strategy, setStrategy] = useState(''); // State for selected strategy
|
||||||
|
const [timeStep, setTimeStep] = useState(100); // State for time step
|
||||||
|
const [rocket, setRocket] = useState({
|
||||||
|
active: false,
|
||||||
|
x: EARTH_X,
|
||||||
|
y: EARTH_Y,
|
||||||
|
trajectory: [],
|
||||||
|
vx: 0,
|
||||||
|
vy: 0,
|
||||||
|
});
|
||||||
|
const [rocketDistance, setRocketDistance] = useState(10000);
|
||||||
|
const [collisionOccurred, setCollisionOccurred] = useState(false);
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<>
|
const fetchAsteroids = async () => {
|
||||||
<div>
|
try {
|
||||||
<p>Scenario</p>
|
const response = await axios.get('http://localhost:8080/api/sentry/');
|
||||||
</div>
|
asteroidsData.current = response.data.near_earth_objects;
|
||||||
</>
|
setAsteroidData(0); // Set initial asteroid
|
||||||
)
|
} catch (error) {
|
||||||
}
|
console.error('Error fetching asteroid data:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchAsteroids();
|
||||||
|
}, []);
|
||||||
|
|
||||||
export default Scenario
|
const estimateMass = (diameter) => {
|
||||||
|
const radius = diameter / 2;
|
||||||
|
const volume = (4 / 3) * Math.PI * Math.pow(radius, 3);
|
||||||
|
return volume * ASTEROID_DENSITY;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setAsteroidData = (index) => {
|
||||||
|
const asteroidData = asteroidsData.current[index];
|
||||||
|
console.log('Asteroid Data:', asteroidData);
|
||||||
|
const size = asteroidData.estimated_diameter.kilometers.estimated_diameter_max;
|
||||||
|
const mass = estimateMass(size);
|
||||||
|
const speed = asteroidData.close_approach_data[0].relative_velocity.kilometers_per_second / 1000;
|
||||||
|
setAsteroid({
|
||||||
|
name: asteroidData.name,
|
||||||
|
size: size,
|
||||||
|
speed: speed,
|
||||||
|
mass: mass,
|
||||||
|
angle: Math.PI / 9,
|
||||||
|
x: 100,
|
||||||
|
y: CANVAS_HEIGHT / 2 - 100,
|
||||||
|
});
|
||||||
|
setTrajectoryPoints([]);
|
||||||
|
calculateForecastPath(size, speed, Math.PI / 9, mass); // Calculate the forecast path once
|
||||||
|
setRocket({ active: false, x: EARTH_X, y: EARTH_Y, trajectory: [], vx: 0, vy: 0 });
|
||||||
|
setRocketDistance(10000);
|
||||||
|
setCollisionOccurred(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAsteroidSelect = (event) => {
|
||||||
|
setAsteroidData(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateForecastPath = (size, speed, angle, mass) => {
|
||||||
|
let x = 100;
|
||||||
|
let y = CANVAS_HEIGHT / 2 - 100;
|
||||||
|
let vx = speed * Math.cos(angle);
|
||||||
|
let vy = speed * Math.sin(angle);
|
||||||
|
const points = [];
|
||||||
|
let iterationCount = 0;
|
||||||
|
const maxIterations = 2000; // Extended limit to allow for longer forecast
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const dx = EARTH_X - x;
|
||||||
|
const dy = EARTH_Y - y;
|
||||||
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
|
||||||
|
// Check if the asteroid hits Earth
|
||||||
|
if (distance <= EARTH_RADIUS_KM * EARTH_DISPLAY_SCALE + size * ASTEROID_DISPLAY_SCALE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply gravitational force
|
||||||
|
const force = (G * EARTH_MASS * mass) / (distance * distance);
|
||||||
|
const ax = force * (dx / distance) / mass;
|
||||||
|
const ay = force * (dy / distance) / mass;
|
||||||
|
|
||||||
|
vx += ax * timeStep;
|
||||||
|
vy += ay * timeStep;
|
||||||
|
|
||||||
|
x += vx * timeStep;
|
||||||
|
y += vy * timeStep;
|
||||||
|
|
||||||
|
points.push(x, y);
|
||||||
|
|
||||||
|
iterationCount++;
|
||||||
|
if (iterationCount >= maxIterations) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the loop if the asteroid goes off screen
|
||||||
|
if (y > CANVAS_HEIGHT * SIMULATION_AREA_MULTIPLIER || x > CANVAS_WIDTH * SIMULATION_AREA_MULTIPLIER || y < -CANVAS_HEIGHT * SIMULATION_AREA_MULTIPLIER || x < -CANVAS_WIDTH * SIMULATION_AREA_MULTIPLIER) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setForecastPoints(points);
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyVelocityImpulse = (asteroid, strategy, rocketDx, rocketDy) => {
|
||||||
|
let impulseX = 0;
|
||||||
|
let impulseY = 0;
|
||||||
|
const angle = Math.atan2(rocketDy, rocketDx);
|
||||||
|
if (strategy === 'Nuclear Detonation') {
|
||||||
|
impulseX = 0.01 * Math.cos(angle);
|
||||||
|
impulseY = 0.01 * Math.sin(angle);
|
||||||
|
} else if (strategy === 'Kinetic Impact') {
|
||||||
|
impulseX = 0.005 * Math.cos(angle);
|
||||||
|
impulseY = 0.005 * Math.sin(angle);
|
||||||
|
}
|
||||||
|
return { vx: asteroid.vx + impulseX, vy: asteroid.vy + impulseY };
|
||||||
|
};
|
||||||
|
|
||||||
|
const simulate = () => {
|
||||||
|
let { x, y, speed, angle, mass } = asteroid;
|
||||||
|
|
||||||
|
let vx = speed * Math.cos(angle);
|
||||||
|
let vy = speed * Math.sin(angle);
|
||||||
|
|
||||||
|
const updateFrame = () => {
|
||||||
|
const dx = EARTH_X - x;
|
||||||
|
const dy = EARTH_Y - y;
|
||||||
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
|
||||||
|
if (distance <= EARTH_RADIUS_KM * EARTH_DISPLAY_SCALE + asteroid.size * ASTEROID_DISPLAY_SCALE) {
|
||||||
|
setSimulationResult('Asteroid collided with Earth!');
|
||||||
|
setIsSimulating(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply gravitational force
|
||||||
|
const force = (G * EARTH_MASS * mass) / (distance * distance);
|
||||||
|
const ax = force * (dx / distance) / mass;
|
||||||
|
const ay = force * (dy / distance) / mass;
|
||||||
|
|
||||||
|
vx += ax * timeStep;
|
||||||
|
vy += ay * timeStep;
|
||||||
|
|
||||||
|
x += vx * timeStep;
|
||||||
|
y += vy * timeStep;
|
||||||
|
|
||||||
|
// Update rocket position
|
||||||
|
setRocket((prev) => {
|
||||||
|
const rocketDx = x - prev.x;
|
||||||
|
const rocketDy = y - prev.y;
|
||||||
|
const rocketDistance = Math.sqrt(rocketDx * rocketDx + rocketDy * rocketDy);
|
||||||
|
const rocketAngle = Math.atan2(rocketDy, rocketDx);
|
||||||
|
|
||||||
|
const rocketVX = ROCKET_SPEED * Math.cos(rocketAngle);
|
||||||
|
const rocketVY = ROCKET_SPEED * Math.sin(rocketAngle);
|
||||||
|
|
||||||
|
const newX = prev.x + rocketVX * timeStep;
|
||||||
|
const newY = prev.y + rocketVY * timeStep;
|
||||||
|
|
||||||
|
if (rocketDistance <= asteroid.size * ASTEROID_DISPLAY_SCALE && !collisionOccurred) {
|
||||||
|
const newVelocity = applyVelocityImpulse({ vx, vy }, strategy, rocketDx, rocketDy);
|
||||||
|
vx = newVelocity.vx;
|
||||||
|
vy = newVelocity.vy;
|
||||||
|
setSimulationResult('Rocket intercepted the asteroid!');
|
||||||
|
setCollisionOccurred(true); // Mark collision occurred
|
||||||
|
return { ...prev, active: false, x: newX, y: newY, vx: 0, vy: 0 }; // Stop the rocket
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
x: newX,
|
||||||
|
y: newY,
|
||||||
|
vx: prev.active ? rocketVX : 0, // Stop velocity if inactive
|
||||||
|
vy: prev.active ? rocketVY : 0, // Stop velocity if inactive
|
||||||
|
trajectory: [...prev.trajectory, newX, newY],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setRocketDistance(rocketDistance);
|
||||||
|
|
||||||
|
if (rocketDistance <= asteroid.size * ASTEROID_DISPLAY_SCALE && !collisionOccurred) {
|
||||||
|
setSimulationResult('Rocket intercepted the asteroid!');
|
||||||
|
setIsSimulating(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y > CANVAS_HEIGHT * SIMULATION_AREA_MULTIPLIER || x > CANVAS_WIDTH * SIMULATION_AREA_MULTIPLIER || y < -CANVAS_HEIGHT * SIMULATION_AREA_MULTIPLIER || x < -CANVAS_WIDTH * SIMULATION_AREA_MULTIPLIER) {
|
||||||
|
setSimulationResult('Asteroid missed Earth!');
|
||||||
|
setIsSimulating(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAsteroid((prev) => ({ ...prev, x, y }));
|
||||||
|
setTrajectoryPoints((prev) => [...prev, x, y]);
|
||||||
|
animationRef.current = window.requestAnimationFrame(updateFrame);
|
||||||
|
};
|
||||||
|
|
||||||
|
setIsSimulating(true);
|
||||||
|
setSimulationResult('');
|
||||||
|
animationRef.current = window.requestAnimationFrame(updateFrame);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSimulate = () => {
|
||||||
|
if (isSimulating) {
|
||||||
|
setIsSimulating(false);
|
||||||
|
window.cancelAnimationFrame(animationRef.current);
|
||||||
|
setSimulationResult('Simulation stopped.');
|
||||||
|
} else {
|
||||||
|
simulate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTimeStepChange = (event, newValue) => {
|
||||||
|
setTimeStep(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAngleChange = (event, newValue) => {
|
||||||
|
setAsteroid((prev) => ({ ...prev, angle: newValue }));
|
||||||
|
calculateForecastPath(asteroid.size, asteroid.speed, newValue, asteroid.mass);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Box sx={{ padding: '20px', maxWidth: '800px', margin: '0 auto', textAlign: 'center' }}>
|
||||||
|
<Typography variant="h4" gutterBottom>
|
||||||
|
Asteroid Collision Scenario
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ marginBottom: '20px' }}>
|
||||||
|
<Select
|
||||||
|
value={asteroid.name}
|
||||||
|
onChange={handleAsteroidSelect}
|
||||||
|
displayEmpty
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
{asteroidsData.current.map((ast, index) => (
|
||||||
|
<MenuItem key={index} value={index}>
|
||||||
|
{ast.name}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ marginBottom: '20px' }}>
|
||||||
|
<Select
|
||||||
|
value={strategy}
|
||||||
|
onChange={(e) => setStrategy(e.target.value)}
|
||||||
|
displayEmpty
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<MenuItem value="">Select Deflection Strategy</MenuItem>
|
||||||
|
<MenuItem value="Nuclear Detonation">Nuclear Detonation</MenuItem>
|
||||||
|
<MenuItem value="Kinetic Impact">Kinetic Impact</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={handleSimulate}
|
||||||
|
style={{ marginBottom: '20px' }}
|
||||||
|
>
|
||||||
|
{isSimulating ? 'Stop Simulation' : 'Simulate'}
|
||||||
|
</Button>
|
||||||
|
{simulationResult && (
|
||||||
|
<Box sx={{ marginBottom: '20px' }}>
|
||||||
|
<Typography variant="h6">Simulation Result</Typography>
|
||||||
|
<Typography>{simulationResult}</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{asteroid.name && (
|
||||||
|
<Box sx={{ marginBottom: '20px' }}>
|
||||||
|
<Typography variant="h6">Asteroid Information</Typography>
|
||||||
|
<Typography><strong>Name:</strong> {asteroid.name}</Typography>
|
||||||
|
<Typography><strong>Size:</strong> {asteroid.size.toFixed(3)} kilometers</Typography>
|
||||||
|
<Typography><strong>Speed:</strong> {(asteroid.speed * 1000).toFixed(3)} km/s</Typography>
|
||||||
|
<Typography><strong>Mass:</strong> {asteroid.mass.toExponential(3)} kg</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Box sx={{ marginBottom: '20px' }}>
|
||||||
|
<Typography>Time Step: {timeStep}</Typography>
|
||||||
|
<Slider
|
||||||
|
value={timeStep}
|
||||||
|
min={10}
|
||||||
|
max={500}
|
||||||
|
step={10}
|
||||||
|
onChange={handleTimeStepChange}
|
||||||
|
aria-labelledby="time-step-slider"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ marginBottom: '20px' }}>
|
||||||
|
<Typography>Initial Angle: {(asteroid.angle * 180 / Math.PI).toFixed(2)}°</Typography>
|
||||||
|
<Slider
|
||||||
|
value={asteroid.angle}
|
||||||
|
min={0}
|
||||||
|
max={Math.PI / 2}
|
||||||
|
step={Math.PI / 180}
|
||||||
|
onChange={handleAngleChange}
|
||||||
|
aria-labelledby="angle-slider"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
<Stage width={CANVAS_WIDTH} height={CANVAS_HEIGHT}>
|
||||||
|
<Layer>
|
||||||
|
<Text text="Earth" fontSize={20} x={EARTH_X - EARTH_RADIUS_KM * EARTH_DISPLAY_SCALE} y={EARTH_Y - 10} />
|
||||||
|
<Circle x={EARTH_X} y={EARTH_Y} radius={EARTH_RADIUS_KM * EARTH_DISPLAY_SCALE} fill="blue" />
|
||||||
|
<Circle x={asteroid.x} y={asteroid.y} radius={asteroid.size * ASTEROID_DISPLAY_SCALE} fill="gray" stroke="black" strokeWidth={1} />
|
||||||
|
{trajectoryPoints.length > 0 && (
|
||||||
|
<Line points={trajectoryPoints.flat()} stroke="red" strokeWidth={2} />
|
||||||
|
)}
|
||||||
|
{forecastPoints.length > 0 && (
|
||||||
|
<Line points={forecastPoints} stroke="gray" strokeWidth={2} dash={[10, 10]} />
|
||||||
|
)}
|
||||||
|
{rocket.active && (
|
||||||
|
<Circle x={rocket.x} y={rocket.y} radius={5} fill="red" />
|
||||||
|
)}
|
||||||
|
{rocket.trajectory.length > 0 && (
|
||||||
|
<Line points={rocket.trajectory} stroke="green" strokeWidth={2} />
|
||||||
|
)}
|
||||||
|
</Layer>
|
||||||
|
</Stage>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Scenario;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import App from "./App";
|
|||||||
import Main from "./pages/main";
|
import Main from "./pages/main";
|
||||||
import Scenario from "./pages/scenario";
|
import Scenario from "./pages/scenario";
|
||||||
import About from "./pages/about";
|
import About from "./pages/about";
|
||||||
|
import Effects from "./pages/effects";
|
||||||
|
import Defenses from "./pages/defenses";
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
@@ -20,8 +22,15 @@ const router = createBrowserRouter([
|
|||||||
{
|
{
|
||||||
path: 'about/',
|
path: 'about/',
|
||||||
element: <About />
|
element: <About />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'effects/',
|
||||||
|
element: <Effects />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'defenses/',
|
||||||
|
element: <Defenses />
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
Reference in New Issue
Block a user