|
1 | | -# SismoView (MVP) |
2 | 1 |
|
3 | | -Monorepo educativo para visualizar propagación de **ondas P/S**, **intensidad** cualitativa y un esqueleto para **tsunami** con aguas someras. |
| 2 | +# SismoView — Monorepo (Backend + Frontend) |
4 | 3 |
|
5 | | -## Pila |
6 | | -- **Backend**: Java 21, Spring Boot 3.3 (Web, Validation, Actuator), OpenAPI (springdoc), Gradle KTS, JUnit 5. |
7 | | -- **Frontend**: Next.js 14 (App Router, TS), React 18, Tailwind, TanStack Query, React Three Fiber (globo 3D), Recharts. |
8 | | -- **Infra**: Dockerfiles y `docker-compose.yml` para levantar local. |
9 | | -- **Fuentes de datos**: USGS GeoJSON para sismos (día/semana). Batimetría: mock. |
| 4 | +Pagina web para visualizar simulaciones sísmicas y de tsunami en un **globo 3D** con estadísticas en tiempo real. |
10 | 5 |
|
11 | | -## Arranque rápido (local) |
| 6 | +> **Stack** |
| 7 | +> |
| 8 | +> - **Frontend:** Next.js 14 + React 18 + TailwindCSS + Three.js + @react-three/fiber + @react-three/drei |
| 9 | +> - **Backend:** Spring Boot 3.3 (Java 24, Gradle Kotlin DSL) |
| 10 | +> - **Formato API:** JSON (DTOs tipados) |
| 11 | +> - **CORS:** habilitado para `http://localhost:3000` por default |
| 12 | +
|
| 13 | +--- |
| 14 | + |
| 15 | +## Tabla de contenidos |
| 16 | + |
| 17 | +- [Arquitectura](#arquitectura) |
| 18 | +- [Requisitos](#requisitos) |
| 19 | +- [Primer arranque rápido](#primer-arranque-rápido) |
| 20 | +- [Frontend](#frontend) |
| 21 | +- [Backend](#backend) |
| 22 | +- [API](#api) |
| 23 | +- [/api/simulate/seismic (POST)](#apisimulateseismic-post) |
| 24 | +- [/api/simulate/tsunami (POST)](#apisimulatetsunami-post) |
| 25 | +- [Despliegue](#despliegue) |
| 26 | +- [Resolución de problemas](#resolución-de-problemas) |
| 27 | +- [Licencia](#licencia) |
| 28 | + |
| 29 | +--- |
| 30 | + |
| 31 | +## Arquitectura |
| 32 | + |
| 33 | +``` |
| 34 | +sismoview/ |
| 35 | +├─ backend/ # Spring Boot (Java 24, Gradle) |
| 36 | +│ ├─ src/main/java/com/sismoview |
| 37 | +│ │ ├─ adapters/rest/ # Controladores REST y DTOs |
| 38 | +│ │ ├─ domain/ # Modelos de dominio y puertos |
| 39 | +│ │ ├─ service/ # Casos de uso (Seismic/Tsunami) |
| 40 | +│ │ └─ config/ # CORS, etc. |
| 41 | +│ ├─ build.gradle.kts |
| 42 | +│ └─ settings.gradle.kts |
| 43 | +│ |
| 44 | +└─ frontend/ # Next.js 14 + React + Three.js |
| 45 | + ├─ app/ # App Router |
| 46 | + ├─ components/ # Globe.tsx, Stats.tsx, etc. |
| 47 | + ├─ public/textures/ # Imágenes del globo (político/normal/specular) |
| 48 | + ├─ .env.local # NEXT_PUBLIC_API_BASE=http://localhost:8080 |
| 49 | + └─ package.json |
| 50 | +``` |
| 51 | + |
| 52 | +--- |
| 53 | + |
| 54 | +## Requisitos |
| 55 | + |
| 56 | +- **Java 21+ (Java 24 probado)** y **Gradle 8.9+** (wrapper incluido) |
| 57 | +- **Node.js 18 o 20 LTS** + **npm 9+** |
| 58 | +- **Git** |
| 59 | + |
| 60 | +> En Windows: PowerShell funciona bien para los comandos. |
| 61 | +
|
| 62 | +--- |
| 63 | + |
| 64 | +## Primer arranque rápido |
| 65 | + |
| 66 | +1) **Backend** (puerto `8080`): |
12 | 67 | ```bash |
13 | | -# Backend |
14 | 68 | cd backend |
15 | | -# Requiere Java 21 y Gradle instalado localmente (o usa tu wrapper) |
16 | | -gradle build |
17 | | -java -jar build/libs/sismoview-backend-0.1.0.jar |
| 69 | +./gradlew bootRun # Windows: .\gradlew.bat bootRun |
| 70 | +``` |
| 71 | +Verás en consola: `Tomcat started on port 8080` y `/actuator` expuesto. |
| 72 | + |
| 73 | +2) **Frontend** (puerto `3000`): |
| 74 | +```bash |
| 75 | +cd frontend |
| 76 | +cp .env.example .env.local # (si no existe) |
| 77 | +# asegúrate de que .env.local tenga: |
| 78 | +# NEXT_PUBLIC_API_BASE=http://localhost:8080 |
18 | 79 |
|
19 | | -# Frontend |
20 | | -cd ../frontend |
21 | | -npm ci |
| 80 | +npm i |
22 | 81 | npm run dev |
23 | | -# abrir http://localhost:3000 |
24 | 82 | ``` |
25 | 83 |
|
26 | | -## Docker Compose |
| 84 | +3) Abre **http://localhost:3000** |
| 85 | + - Ingresa lat/lon/magnitud y presiona **Simular** |
| 86 | + - Verás el **globo 3D** con anillos P/S y el panel de **estadísticas** (arrivals / intensidad). |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +## Frontend |
| 91 | + |
| 92 | +- **Rutas y componentes clave** |
| 93 | + - `app/page.tsx`: pantalla principal con formulario, layout y panel lateral. |
| 94 | + - `components/Globe.tsx`: escena de **Three.js** con: |
| 95 | + - `Canvas` de `@react-three/fiber` |
| 96 | + - `OrbitControls` de `@react-three/drei` |
| 97 | + - Texturas opcionales en `public/textures/`: |
| 98 | + - `earth_political_4k.jpg` (mapa político) |
| 99 | + - `earth_normal_2k.jpg` (normal map, opcional) |
| 100 | + - `earth_specular_2k.jpg` (specular mask, opcional) |
| 101 | + |
| 102 | +- **Variables de entorno** |
| 103 | + - `NEXT_PUBLIC_API_BASE` → URL del backend (ej: `http://localhost:8080`) |
| 104 | + |
| 105 | +- **Scripts** |
27 | 106 | ```bash |
28 | | -docker compose up --build |
29 | | -# FE en http://localhost:3000 | BE en http://localhost:8080 |
| 107 | +npm run dev # desarrollo (3000) |
| 108 | +npm run build # build producción |
| 109 | +npm run start # sirve la build (3000) |
30 | 110 | ``` |
31 | 111 |
|
32 | | -## Endpoints |
33 | | -- `POST /api/simulate/seismic` |
34 | | -- `POST /api/simulate/tsunami` |
35 | | -- `GET /api/live/earthquakes?window=day|week` |
36 | | -- `GET /actuator/health` |
37 | | -- Swagger: `/swagger-ui.html` |
| 112 | +- **Nota Texturas** |
| 113 | + - Coloca las imágenes en `frontend/public/textures/` con los nombres indicados. |
| 114 | + - Acceso en runtime: `/textures/earth_political_4k.jpg` (Next sirve `public/` desde la raíz). |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## Backend |
| 119 | + |
| 120 | +- **Módulos principales** |
| 121 | + - `SismoViewBackendApplication` (Spring Boot) |
| 122 | + - `SeismicService` y `TsunamiService` (lógica de simulación) |
| 123 | + - `SismoController` (controlador REST) |
| 124 | + - DTOs en `adapters/rest/dto/*` (request/response) |
| 125 | + - Modelos en `domain/models/*` |
| 126 | + |
| 127 | +- **Build / Calidad** |
| 128 | +```bash |
| 129 | +cd backend |
| 130 | +./gradlew clean checkstyleMain checkstyleTest build |
| 131 | +# JAR en build/libs/... |
| 132 | +``` |
| 133 | + |
| 134 | +- **Run** |
| 135 | +```bash |
| 136 | +./gradlew bootRun |
| 137 | +# o |
| 138 | +java -jar build/libs/sismoview-backend-*.jar |
| 139 | +``` |
| 140 | + |
| 141 | +- **CORS** |
| 142 | + - `WebConfig` habilita `http://localhost:3000` y `https://*` sobre `/api/**`. |
| 143 | + |
| 144 | +--- |
| 145 | + |
| 146 | +## API |
| 147 | + |
| 148 | +### `/api/simulate/seismic` (POST) |
| 149 | + |
| 150 | +**Body** (JSON): |
| 151 | +```jsonc |
| 152 | +{ |
| 153 | + "lat": 10.5, |
| 154 | + "lon": 166.3, |
| 155 | + "depthKm": 10, |
| 156 | + "magnitude": 6.3, |
| 157 | + "cities": [ |
| 158 | + { "name": "Bogotá", "lat": 4.711, "lon": -74.0721 }, |
| 159 | + { "name": "Tokio", "lat": 35.6762, "lon": 139.6503 } |
| 160 | + ] |
| 161 | +} |
| 162 | +``` |
| 163 | + |
| 164 | +**Response**: |
| 165 | +```jsonc |
| 166 | +{ |
| 167 | + "rings": { |
| 168 | + "p": [ /* RingSegment[]: {centerLat, centerLon, bearingDeg, distanceKm} */ ], |
| 169 | + "s": [ /* RingSegment[] */ ] |
| 170 | + }, |
| 171 | + "arrivals": [ |
| 172 | + { "city": "Bogotá", "phase": "P", "minutes": 36.2 }, |
| 173 | + { "city": "Bogotá", "phase": "S", "minutes": 62.0 }, |
| 174 | + { "city": "Tokio", "phase": "P", "minutes": 9.7 }, |
| 175 | + { "city": "Tokio", "phase": "S", "minutes": 16.7 } |
| 176 | + ], |
| 177 | + "intensity": { |
| 178 | + "levels": [ /* number[] 1..8 */ ], |
| 179 | + "legend": [ |
| 180 | + { "label": "1 Muy débil", "color": "#60a5fa" }, |
| 181 | + { "label": "8 Extremo", "color": "#ef4444" } |
| 182 | + ] |
| 183 | + } |
| 184 | +} |
| 185 | +``` |
| 186 | + |
| 187 | +### `/api/simulate/tsunami` (POST) |
| 188 | + |
| 189 | +**Body** (JSON): |
| 190 | +```jsonc |
| 191 | +{ |
| 192 | + "lat": 10.5, |
| 193 | + "lon": 166.3, |
| 194 | + "magnitude": 6.3 |
| 195 | +} |
| 196 | +``` |
| 197 | + |
| 198 | +**Response**: |
| 199 | +```jsonc |
| 200 | +{ |
| 201 | + "legend": [ |
| 202 | + { "label": "0–1 m", "color": "#38bdf8" }, |
| 203 | + { "label": "1–3 m", "color": "#22c55e" } |
| 204 | + ], |
| 205 | + "grid": { "cols": 360, "rows": 180 } // ejemplo/placeholder |
| 206 | +} |
| 207 | +``` |
| 208 | + |
| 209 | +> *Los nombres exactos de campos responden a los DTOs del backend (`SeismicRequest`, `SeismicResponse`, `TsunamiResponse`, `Arrival`, `RingSegment`, `IntensityResult`, `LegendItem`).* |
| 210 | +
|
| 211 | +--- |
| 212 | + |
| 213 | +## Despliegue |
| 214 | + |
| 215 | +- **Frontend**: `npm run build` y servir `.next/` con `next start` o tu plataforma (Vercel). |
| 216 | +- **Backend**: publicar el JAR en tu infraestructura (Docker/Cloud Run/EC2/etc). |
| 217 | + |
| 218 | +**Docker compose (opcional y básico):** |
| 219 | +```yaml |
| 220 | +version: '3.9' |
| 221 | +services: |
| 222 | + backend: |
| 223 | + build: ./backend |
| 224 | + ports: ["8080:8080"] |
| 225 | + frontend: |
| 226 | + build: ./frontend |
| 227 | + ports: ["3000:3000"] |
| 228 | + environment: |
| 229 | + NEXT_PUBLIC_API_BASE: "http://backend:8080" |
| 230 | + depends_on: [backend] |
| 231 | +``` |
| 232 | +
|
| 233 | +--- |
| 234 | +
|
| 235 | +## Resolución de problemas |
| 236 | +
|
| 237 | +- **Texturas 404** |
| 238 | + - Asegúrate de tener los archivos en `frontend/public/textures/` con el nombre correcto. |
| 239 | +- **No rota/zooma el globo** |
| 240 | + - Comprueba que `OrbitControls` está montado y que el canvas no tiene un overlay encima. |
| 241 | +- **Conflictos @react-three/drei / fiber / three** |
| 242 | + - Usa versiones compatibles. Recomendado: `three@0.160.x`, `@react-three/fiber@^9`, `@react-three/drei@^10`. |
| 243 | +- **Checkstyle fallando** |
| 244 | + - Ejecuta `./gradlew checkstyleMain checkstyleTest` y corrige los archivos reportados en `backend/build/reports/checkstyle/`. |
| 245 | +- **CORS** |
| 246 | + - Si cambias el origen del frontend, actualiza `WebConfig#addCorsMappings`. |
| 247 | + |
| 248 | +--- |
| 249 | + |
| 250 | +## Licencia |
38 | 251 |
|
39 | | -> Uso educativo. No apto para operación ni pronóstico. |
| 252 | +Este repositorio es un ejemplo/MVP para fines educativos. Asegura que las texturas usadas respeten sus licencias de origen. |
0 commit comments