重新定义天体大小的展现逻辑
parent
2e31f89464
commit
14fb922cd2
|
|
@ -1,148 +0,0 @@
|
|||
# Scheduled Jobs System - Code Review Summary
|
||||
|
||||
## Overview
|
||||
This document summarizes the code review and cleanup performed on the scheduled jobs system.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. Backend - Removed Debug Logs with Emojis
|
||||
|
||||
#### `app/jobs/predefined.py`
|
||||
- Removed emoji icons from log messages (🌍, 📋, 🔄, ✅, ❌, 🎉, ⚠️)
|
||||
- Changed `logger.info` to `logger.debug` for detailed operation logs
|
||||
- Kept `logger.info` only for high-level operation summaries
|
||||
- Kept `logger.error` and `logger.warning` for error conditions
|
||||
|
||||
**Before:**
|
||||
```python
|
||||
logger.info(f"🌍 Starting solar system position sync: days={days}")
|
||||
logger.info(f"🔄 Fetching positions for {body.name}")
|
||||
logger.info(f"✅ Saved {count} positions for {body.name}")
|
||||
```
|
||||
|
||||
**After:**
|
||||
```python
|
||||
logger.info(f"Starting solar system position sync: days={days}")
|
||||
logger.debug(f"Fetching positions for {body.name}")
|
||||
logger.debug(f"Saved {count} positions for {body.name}")
|
||||
```
|
||||
|
||||
#### `app/jobs/registry.py`
|
||||
- Changed task registration log from `logger.info` to `logger.debug`
|
||||
- Changed task execution logs from `logger.info` to `logger.debug`
|
||||
- Removed emoji icons (📋, 🚀, ✅)
|
||||
|
||||
#### `app/services/scheduler_service.py`
|
||||
- Removed emoji icons from all log messages (⏰, ❌, ✅)
|
||||
- Kept important lifecycle logs as `logger.info` (start, stop, job scheduling)
|
||||
- Changed detailed execution logs to `logger.debug`
|
||||
|
||||
### 2. Backend - Removed Unused Imports
|
||||
|
||||
#### `app/api/scheduled_job.py`
|
||||
- Removed unused imports: `update`, `delete` from sqlalchemy
|
||||
|
||||
**Before:**
|
||||
```python
|
||||
from sqlalchemy import select, update, delete
|
||||
```
|
||||
|
||||
**After:**
|
||||
```python
|
||||
from sqlalchemy import select
|
||||
```
|
||||
|
||||
### 3. Frontend - Removed Debug Console Logs
|
||||
|
||||
#### `pages/admin/ScheduledJobs.tsx`
|
||||
- Removed `console.log` statements from `loadAvailableTasks()`
|
||||
- Removed `console.error` statements from `loadAvailableTasks()`
|
||||
- Removed `console.log` statements from `handleEdit()`
|
||||
- Removed `console.error` from error handling (kept only toast messages)
|
||||
|
||||
**Removed:**
|
||||
```typescript
|
||||
console.log('Loaded available tasks:', result);
|
||||
console.error('Failed to load available tasks:', error);
|
||||
console.log('Editing record:', record);
|
||||
console.log('Available tasks:', availableTasks);
|
||||
console.error(error);
|
||||
```
|
||||
|
||||
## Code Quality Improvements
|
||||
|
||||
### 1. Consistent Logging Levels
|
||||
- **ERROR**: For failures that prevent operations
|
||||
- **WARNING**: For non-critical issues (e.g., "No bodies found")
|
||||
- **INFO**: For high-level operation summaries
|
||||
- **DEBUG**: For detailed operation traces
|
||||
|
||||
### 2. Clean User-Facing Messages
|
||||
- All user-facing error messages use toast notifications
|
||||
- No console output in production frontend code
|
||||
- Backend logs are professional and parseable
|
||||
|
||||
### 3. Transaction Safety
|
||||
- Using SQLAlchemy savepoints (`begin_nested()`) for isolated error handling
|
||||
- Proper rollback and commit patterns
|
||||
- Error messages include full traceback for debugging
|
||||
|
||||
## Testing Results
|
||||
|
||||
### Import Test
|
||||
✓ All backend imports successful
|
||||
✓ Task registry properly initialized
|
||||
✓ 2 tasks registered:
|
||||
- sync_solar_system_positions
|
||||
- sync_celestial_events
|
||||
|
||||
### Task Schema Test
|
||||
✓ Task parameters properly defined:
|
||||
- body_ids (array, optional, default=None)
|
||||
- days (integer, optional, default=7)
|
||||
- source (string, optional, default=nasa_horizons_cron)
|
||||
|
||||
### Integration Test
|
||||
✓ Position constraint fixed (nasa_horizons_cron added to CHECK constraint)
|
||||
✓ Manual job execution successful
|
||||
✓ 26 celestial bodies synced with 52 positions
|
||||
✓ Task record properly created and updated
|
||||
✓ No failures during execution
|
||||
|
||||
## Remaining Console Logs (Other Admin Pages)
|
||||
|
||||
The following console logs exist in other admin pages but were left unchanged as they're outside the scope of this scheduled jobs feature:
|
||||
|
||||
- `SystemSettings.tsx`: 1 console.error
|
||||
- `Users.tsx`: 2 console.error
|
||||
- `Dashboard.tsx`: 1 console.error
|
||||
- `StaticData.tsx`: 1 console.error
|
||||
- `CelestialBodies.tsx`: 2 (1 error, 1 for JSON parsing)
|
||||
- `NASADownload.tsx`: 3 (2 debug logs, 1 error)
|
||||
|
||||
## Files Modified
|
||||
|
||||
### Backend
|
||||
1. `/backend/app/jobs/predefined.py` - Removed emoji logs, adjusted log levels
|
||||
2. `/backend/app/jobs/registry.py` - Changed to debug logging
|
||||
3. `/backend/app/services/scheduler_service.py` - Removed emojis, adjusted log levels
|
||||
4. `/backend/app/api/scheduled_job.py` - Removed unused imports
|
||||
|
||||
### Frontend
|
||||
1. `/frontend/src/pages/admin/ScheduledJobs.tsx` - Removed all console logs
|
||||
|
||||
### Database
|
||||
1. `/backend/scripts/fix_position_source_constraint.py` - Fixed CHECK constraint
|
||||
|
||||
## Summary
|
||||
|
||||
All scheduled jobs related code has been reviewed and cleaned:
|
||||
- ✅ No emoji icons in production logs
|
||||
- ✅ Appropriate logging levels (ERROR/WARNING/INFO/DEBUG)
|
||||
- ✅ No console.log/console.error in frontend
|
||||
- ✅ No unused imports
|
||||
- ✅ All imports and registrations working
|
||||
- ✅ Database constraints fixed
|
||||
- ✅ Integration tests passing
|
||||
|
||||
The code is now production-ready with clean, professional logging suitable for monitoring and debugging.
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
# 恒星系统架构改造 - 进度报告
|
||||
|
||||
## ✅ 已完成工作
|
||||
|
||||
### 1. 数据库架构改造
|
||||
- ✅ 创建 `star_systems` 表
|
||||
- ✅ 添加太阳系初始记录(id=1)
|
||||
- ✅ 扩展 `celestial_bodies` 表(添加 `system_id` 字段)
|
||||
- ✅ 更新所有太阳系天体 `system_id = 1`(30个天体)
|
||||
|
||||
### 2. ORM 模型
|
||||
- ✅ 创建 `StarSystem` ORM 模型
|
||||
- ✅ 更新 `CelestialBody` ORM 模型(添加 system_id 关系)
|
||||
- ✅ 在 `__init__.py` 中注册 StarSystem
|
||||
|
||||
### 3. 数据迁移
|
||||
- ✅ 编写完整的数据迁移脚本(`scripts/migrate_interstellar_data.py`)
|
||||
- ✅ 实现自动中文名翻译功能
|
||||
- ✅ 实现行星数据去重逻辑
|
||||
- ✅ 成功迁移 578 个系外恒星系统
|
||||
- ✅ 成功迁移 898 颗系外行星(去重后)
|
||||
|
||||
### 4. 后端服务层
|
||||
- ✅ 创建 `StarSystemService`(`app/services/star_system_service.py`)
|
||||
- 支持 CRUD 操作
|
||||
- 支持搜索和分页
|
||||
- 支持获取恒星系及其所有天体
|
||||
- 支持统计功能
|
||||
|
||||
- ✅ 创建 Pydantic 模型(`app/models/star_system.py`)
|
||||
- StarSystemBase
|
||||
- StarSystemCreate
|
||||
- StarSystemUpdate
|
||||
- StarSystemResponse
|
||||
- StarSystemWithBodies
|
||||
- StarSystemStatistics
|
||||
|
||||
### 5. 迁移数据统计
|
||||
```
|
||||
恒星系统总数: 579
|
||||
- 太阳系: 1
|
||||
- 系外恒星系: 578
|
||||
|
||||
天体总数: 928
|
||||
- 太阳系天体: 30(含太阳、行星、矮行星、卫星、探测器、彗星)
|
||||
- 系外行星: 898(已去重)
|
||||
|
||||
数据质量:
|
||||
- 去重前行星记录: ~3000+
|
||||
- 去重后行星记录: 898
|
||||
- 去重率: ~70%
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚧 剩余工作
|
||||
|
||||
### 1. 后端 API 开发
|
||||
- [ ] 创建 StarSystem API 路由
|
||||
- GET /api/star-systems(获取所有恒星系统)
|
||||
- GET /api/star-systems/{id}(获取单个恒星系统)
|
||||
- GET /api/star-systems/{id}/bodies(获取恒星系及其天体)
|
||||
- POST /api/admin/star-systems(创建恒星系统)
|
||||
- PUT /api/admin/star-systems/{id}(更新恒星系统)
|
||||
- DELETE /api/admin/star-systems/{id}(删除恒星系统)
|
||||
- GET /api/star-systems/statistics(获取统计信息)
|
||||
|
||||
- [ ] 更新 CelestialBody API
|
||||
- 添加 `system_id` 查询参数
|
||||
- 添加 `include_no_system` 参数(用于包含探测器等)
|
||||
|
||||
### 2. 后台管理界面(Admin Frontend)
|
||||
- [ ] 创建恒星系统管理页面(`/admin/star-systems`)
|
||||
- 列表展示(支持搜索、分页)
|
||||
- 新增恒星系统
|
||||
- 编辑恒星系统
|
||||
- 删除恒星系统(不可删除太阳系)
|
||||
- 查看恒星系详情(含所有行星)
|
||||
|
||||
- [ ] 改造天体管理页面(`/admin/celestial-bodies`)
|
||||
- **关键改动**:先选择恒星系,再列出该恒星系的天体
|
||||
- 添加恒星系选择器(下拉框)
|
||||
- 根据选中的恒星系过滤天体列表
|
||||
- 新增天体时自动设置 `system_id`
|
||||
- 支持在恒星系之间移动天体
|
||||
|
||||
### 3. 前端界面更新
|
||||
- [ ] 更新 GalaxyScene 组件
|
||||
- 使用新的 `/api/star-systems` API
|
||||
- 移除前端行星去重代码
|
||||
- 优化恒星点击事件(使用后端返回的完整数据)
|
||||
|
||||
- [ ] 更新 App.tsx 查询逻辑
|
||||
- Solar 视图:查询 `system_id=1` 的天体
|
||||
- Galaxy 视图:查询所有恒星系统
|
||||
|
||||
### 4. 菜单配置
|
||||
- [ ] 在后台管理菜单中添加"恒星系统管理"入口
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据模型关系图
|
||||
|
||||
```
|
||||
star_systems (579条记录)
|
||||
├── id=1: Solar System (太阳系)
|
||||
│ └── celestial_bodies (30条)
|
||||
│ ├── Sun (star)
|
||||
│ ├── Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune (planet)
|
||||
│ ├── Pluto, Ceres, Haumea, Makemake, Eris (dwarf_planet)
|
||||
│ ├── Moon, Io, Europa, Ganymede, Callisto (satellite)
|
||||
│ ├── Voyager 1, Voyager 2, Parker Solar Probe... (probe)
|
||||
│ └── Halley, NEOWISE, C/2020 F3 (comet)
|
||||
│
|
||||
├── id=2: Proxima Cen System (比邻星系统)
|
||||
│ └── celestial_bodies (2条)
|
||||
│ ├── Proxima Cen b (比邻星 b)
|
||||
│ └── Proxima Cen d (比邻星 d)
|
||||
│
|
||||
├── id=3: TRAPPIST-1 System
|
||||
│ └── celestial_bodies (7条)
|
||||
│ └── TRAPPIST-1 b/c/d/e/f/g/h
|
||||
│
|
||||
└── ... (575 more systems)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 下一步行动
|
||||
|
||||
**立即可做:**
|
||||
1. 完成 StarSystem API 路由
|
||||
2. 测试 API 端点
|
||||
3. 开发后台管理界面
|
||||
|
||||
**预计工作量:**
|
||||
- 后端 API:1-2小时
|
||||
- 后台界面:3-4小时
|
||||
- 前端更新:1-2小时
|
||||
- 测试验证:1小时
|
||||
|
||||
**总计:6-9小时**
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术要点
|
||||
|
||||
### 中文名翻译规则
|
||||
```python
|
||||
# 恒星名翻译示例
|
||||
Proxima Cen → 比邻星
|
||||
Kepler-442 → 开普勒-442
|
||||
TRAPPIST-1 → TRAPPIST-1
|
||||
HD 40307 → HD 40307
|
||||
|
||||
# 行星名翻译示例
|
||||
Proxima Cen b → 比邻星 b
|
||||
Kepler-442 b → 开普勒-442 b
|
||||
```
|
||||
|
||||
### 去重逻辑
|
||||
- 按行星名称(name)去重
|
||||
- 保留字段最完整的记录(非NULL字段最多的)
|
||||
- 平均每个恒星系从5.2条记录减少到1.6条(效率提升70%)
|
||||
|
||||
### 查询优化
|
||||
```sql
|
||||
-- Solar 视图
|
||||
SELECT * FROM celestial_bodies WHERE system_id = 1;
|
||||
|
||||
-- Galaxy 视图
|
||||
SELECT * FROM star_systems WHERE id > 1;
|
||||
|
||||
-- 恒星系详情
|
||||
SELECT * FROM celestial_bodies WHERE system_id = ?;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v1.0
|
||||
**更新时间**: 2025-12-05 19:10
|
||||
**状态**: 数据迁移完成,API开发进行中
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Add missing real_radius data for solar system bodies"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.services.db_service import celestial_body_service
|
||||
|
||||
# Real radii from NASA data (in km)
|
||||
MISSING_RADII = {
|
||||
'10': 696000, # Sun
|
||||
'999': 1188, # Pluto
|
||||
'2000001': 476, # Ceres
|
||||
'136199': 1163, # Eris
|
||||
'136108': 816, # Haumea
|
||||
'136472': 715, # Makemake
|
||||
}
|
||||
|
||||
async def add_missing_radii():
|
||||
"""Add real_radius to bodies that are missing it"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
print("=" * 70)
|
||||
print("Adding missing real_radius data")
|
||||
print("=" * 70)
|
||||
|
||||
for body_id, radius in MISSING_RADII.items():
|
||||
body = await celestial_body_service.get_body_by_id(body_id, session)
|
||||
|
||||
if not body:
|
||||
print(f"❌ Body {body_id} not found")
|
||||
continue
|
||||
|
||||
# Get existing extra_data or create new dict
|
||||
extra_data = body.extra_data.copy() if body.extra_data else {}
|
||||
|
||||
# Add real_radius
|
||||
extra_data['real_radius'] = radius
|
||||
|
||||
# Update body
|
||||
updated = await celestial_body_service.update_body(
|
||||
body_id,
|
||||
{'extra_data': extra_data},
|
||||
session
|
||||
)
|
||||
|
||||
if updated:
|
||||
print(f"✅ {body.name:<20} (ID: {body_id:<10}): Added real_radius = {radius:>8} km")
|
||||
else:
|
||||
print(f"❌ {body.name:<20} (ID: {body_id:<10}): Update failed")
|
||||
|
||||
await session.commit()
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("✅ All missing real_radius data added successfully!")
|
||||
print("=" * 70)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(add_missing_radii())
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Analyze the size calculation problem"""
|
||||
import json
|
||||
|
||||
print("=" * 80)
|
||||
print("SIZE CALCULATION ANALYSIS")
|
||||
print("=" * 80)
|
||||
|
||||
configs = {
|
||||
"planet": {"ratio": 0.00008},
|
||||
"dwarf_planet": {"ratio": 0.00015},
|
||||
}
|
||||
|
||||
bodies = {
|
||||
'Jupiter': {'type': 'planet', 'radius': 69911},
|
||||
'Saturn': {'type': 'planet', 'radius': 58232},
|
||||
'Earth': {'type': 'planet', 'radius': 6371},
|
||||
'Ceres': {'type': 'dwarf_planet', 'radius': 476},
|
||||
'Pluto': {'type': 'dwarf_planet', 'radius': 1188},
|
||||
}
|
||||
|
||||
print("\n1. CALCULATED DISPLAY SIZES:")
|
||||
print("-" * 80)
|
||||
for name, body in bodies.items():
|
||||
ratio = configs[body['type']]['ratio']
|
||||
size = body['radius'] * ratio
|
||||
print(f"{name:<15}: {body['radius']:>6} km * {ratio:.6f} = {size:.4f}")
|
||||
|
||||
print("\n2. SIZE RATIOS (relative to Earth):")
|
||||
print("-" * 80)
|
||||
earth_size = bodies['Earth']['radius'] * configs['planet']['ratio']
|
||||
for name, body in bodies.items():
|
||||
ratio = configs[body['type']]['ratio']
|
||||
size = body['radius'] * ratio
|
||||
relative = size / earth_size
|
||||
print(f"{name:<15}: {size:.4f} / {earth_size:.4f} = {relative:.2f}x Earth")
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print("⚠️ PROBLEM IDENTIFIED:")
|
||||
print("=" * 80)
|
||||
print("Planet ratio: 0.00008")
|
||||
print("Dwarf planet ratio: 0.00015 (1.875x larger!)")
|
||||
print()
|
||||
print("This means dwarf planets are artificially ENLARGED by 1.875x")
|
||||
print("relative to regular planets!")
|
||||
print()
|
||||
print("IMPACT:")
|
||||
print(" • Small dwarf planets (Ceres) appear TOO LARGE")
|
||||
print(" • Large planets (Jupiter, Saturn) appear correctly sized")
|
||||
print(" • But the ratio between them is WRONG")
|
||||
print()
|
||||
print("SOLUTION:")
|
||||
print(" → Use the SAME ratio for all body types")
|
||||
print(" → Recommended: ratio = 0.00008 for all types")
|
||||
print("=" * 80)
|
||||
|
||||
# Show what sizes would be with unified ratio
|
||||
print("\n3. SIZES WITH UNIFIED RATIO (0.00008):")
|
||||
print("-" * 80)
|
||||
unified_ratio = 0.00008
|
||||
for name, body in bodies.items():
|
||||
size = body['radius'] * unified_ratio
|
||||
relative = size / earth_size
|
||||
print(f"{name:<15}: {body['radius']:>6} km * {unified_ratio:.6f} = {size:.4f} ({relative:.2f}x Earth)")
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Check all positions for Earth"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.services.db_service import position_service
|
||||
|
||||
async def check_all_positions():
|
||||
"""Check all position data for Earth"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get all positions (no time filter)
|
||||
positions = await position_service.get_positions(
|
||||
body_id="399",
|
||||
start_time=None,
|
||||
end_time=None,
|
||||
session=session
|
||||
)
|
||||
|
||||
print(f"Total positions for Earth: {len(positions)}")
|
||||
|
||||
if positions:
|
||||
print(f"\nFirst position: {positions[0].time}")
|
||||
print(f"Last position: {positions[-1].time}")
|
||||
print("\nSample of last 5 positions:")
|
||||
for pos in positions[-5:]:
|
||||
print(f" {pos.time}: ({pos.x:.6f}, {pos.y:.6f}, {pos.z:.6f})")
|
||||
else:
|
||||
print("\n❌ No positions at all!")
|
||||
print("You need to download position data first.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(check_all_positions())
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Check real_radius for all planets"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from sqlalchemy import select
|
||||
from app.models.db.celestial_body import CelestialBody
|
||||
|
||||
async def check_radii():
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get all planets and dwarf planets
|
||||
stmt = select(CelestialBody).where(
|
||||
CelestialBody.type.in_(['planet', 'dwarf_planet', 'star'])
|
||||
).order_by(CelestialBody.name)
|
||||
|
||||
result = await session.execute(stmt)
|
||||
bodies = result.scalars().all()
|
||||
|
||||
print("Body Name | Type | Real Radius (km)")
|
||||
print("-" * 60)
|
||||
|
||||
for body in bodies:
|
||||
radius = body.extra_data.get('real_radius') if body.extra_data else None
|
||||
print(f"{body.name:20s} | {body.type:13s} | {radius if radius else 'N/A'}")
|
||||
|
||||
# Calculate ratios relative to Earth
|
||||
earth_radius = 6371
|
||||
print("\n" + "=" * 60)
|
||||
print("Size ratios relative to Earth (6371 km):")
|
||||
print("=" * 60)
|
||||
|
||||
for body in bodies:
|
||||
if body.extra_data and body.extra_data.get('real_radius'):
|
||||
radius = body.extra_data['real_radius']
|
||||
ratio = radius / earth_radius
|
||||
print(f"{body.name:20s}: {radius:8.0f} km = {ratio:6.2f}x Earth")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(check_radii())
|
||||
29
check_api.py
29
check_api.py
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
import requests
|
||||
import sys
|
||||
|
||||
def check_api():
|
||||
url = "http://localhost:8000/api/celestial/positions"
|
||||
try:
|
||||
response = requests.get(url, timeout=5)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
bodies = data.get("bodies", [])
|
||||
print(f"API returned {len(bodies)} bodies.")
|
||||
|
||||
targets = [b for b in bodies if b.get("name") in ["Earth", "Jupiter"]]
|
||||
for t in targets:
|
||||
print(f"Body: {t.get('name')}")
|
||||
print(f" Keys: {list(t.keys())}")
|
||||
print(f" Extra Data: {t.get('extra_data')}")
|
||||
if t.get('extra_data'):
|
||||
print(f" Real Radius: {t.get('extra_data', {}).get('real_radius')}")
|
||||
else:
|
||||
print(" Real Radius: MISSING")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error checking API: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
check_api()
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Check celestial_type_configs system setting"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.services.system_settings_service import system_settings_service
|
||||
|
||||
async def check_configs():
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get celestial_type_configs
|
||||
configs = await system_settings_service.get_setting_value('celestial_type_configs', session)
|
||||
|
||||
if configs:
|
||||
print("=" * 70)
|
||||
print("CELESTIAL TYPE CONFIGS")
|
||||
print("=" * 70)
|
||||
print(json.dumps(configs, indent=2))
|
||||
print("\n" + "=" * 70)
|
||||
print("CALCULATED SIZES (assuming Earth radius = 6371 km)")
|
||||
print("=" * 70)
|
||||
|
||||
# Test calculation for different body types
|
||||
test_bodies = {
|
||||
'Sun': {'type': 'star', 'real_radius': 696000},
|
||||
'Jupiter': {'type': 'planet', 'real_radius': 69911},
|
||||
'Saturn': {'type': 'planet', 'real_radius': 58232},
|
||||
'Earth': {'type': 'planet', 'real_radius': 6371},
|
||||
'Mars': {'type': 'planet', 'real_radius': 3389},
|
||||
'Ceres': {'type': 'dwarf_planet', 'real_radius': 476},
|
||||
'Pluto': {'type': 'dwarf_planet', 'real_radius': 1188},
|
||||
}
|
||||
|
||||
for name, body in test_bodies.items():
|
||||
body_type = body['type']
|
||||
real_radius = body['real_radius']
|
||||
|
||||
if body_type in configs and 'ratio' in configs[body_type]:
|
||||
ratio = configs[body_type]['ratio']
|
||||
calculated_size = real_radius * ratio
|
||||
print(f"{name:<15} ({body_type:<13}): {real_radius:>7} km * {ratio:.6f} = {calculated_size:.4f}")
|
||||
else:
|
||||
print(f"{name:<15} ({body_type:<13}): No ratio config found")
|
||||
|
||||
else:
|
||||
print("❌ celestial_type_configs not found in system settings")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(check_configs())
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Check which solar system bodies are missing real_radius"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from sqlalchemy import select
|
||||
from app.models.db.celestial_body import CelestialBody
|
||||
|
||||
async def check_missing_radii():
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Solar System body IDs
|
||||
solar_ids = ['10', '199', '299', '399', '499', '599', '699', '799', '899', '999',
|
||||
'2000001', '136199', '136108', '136472']
|
||||
|
||||
stmt = select(CelestialBody).where(CelestialBody.id.in_(solar_ids))
|
||||
result = await session.execute(stmt)
|
||||
bodies = result.scalars().all()
|
||||
|
||||
print("=" * 70)
|
||||
print("SOLAR SYSTEM BODIES - Missing real_radius Check")
|
||||
print("=" * 70)
|
||||
|
||||
has_radius = []
|
||||
missing_radius = []
|
||||
|
||||
for body in bodies:
|
||||
radius = body.extra_data.get('real_radius') if body.extra_data else None
|
||||
if radius:
|
||||
has_radius.append((body.name, body.type, radius))
|
||||
else:
|
||||
missing_radius.append((body.name, body.type))
|
||||
|
||||
print(f"\n✅ Bodies WITH real_radius ({len(has_radius)}):")
|
||||
print("-" * 70)
|
||||
for name, btype, radius in sorted(has_radius, key=lambda x: x[2], reverse=True):
|
||||
print(f" {name:<20} ({btype:<15}): {radius:>8.0f} km")
|
||||
|
||||
print(f"\n❌ Bodies MISSING real_radius ({len(missing_radius)}):")
|
||||
print("-" * 70)
|
||||
for name, btype in sorted(missing_radius):
|
||||
print(f" {name:<20} ({btype})")
|
||||
|
||||
if missing_radius:
|
||||
print("\n⚠️ WARNING: Bodies without real_radius will use TYPE_SIZES fallback!")
|
||||
print(" This causes INCONSISTENT scaling!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(check_missing_radii())
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Check if positions exist in database for Earth"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.services.db_service import position_service
|
||||
|
||||
async def check_positions():
|
||||
"""Check if we have position data for Earth"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
now = datetime.utcnow()
|
||||
recent_window = now - timedelta(hours=24)
|
||||
|
||||
positions = await position_service.get_positions(
|
||||
body_id="399",
|
||||
start_time=recent_window,
|
||||
end_time=now,
|
||||
session=session
|
||||
)
|
||||
|
||||
print(f"Checking positions for Earth (ID: 399)")
|
||||
print(f"Time range: {recent_window} to {now}")
|
||||
print(f"Found {len(positions)} positions")
|
||||
|
||||
if positions:
|
||||
latest = positions[-1]
|
||||
print(f"\nLatest position:")
|
||||
print(f" Time: {latest.time}")
|
||||
print(f" X: {latest.x}, Y: {latest.y}, Z: {latest.z}")
|
||||
else:
|
||||
print("\n❌ No recent positions found for Earth!")
|
||||
print("This explains why the API is failing.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(check_positions())
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Check real_radius for solar system planets only"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from sqlalchemy import select
|
||||
from app.models.db.celestial_body import CelestialBody
|
||||
|
||||
async def check_solar_system():
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Solar System body IDs
|
||||
solar_ids = ['10', '199', '299', '399', '499', '599', '699', '799', '899', '999',
|
||||
'2000001', '136199', '136108', '136472']
|
||||
|
||||
stmt = select(CelestialBody).where(CelestialBody.id.in_(solar_ids))
|
||||
result = await session.execute(stmt)
|
||||
bodies = result.scalars().all()
|
||||
|
||||
print("=" * 70)
|
||||
print("SOLAR SYSTEM CELESTIAL BODIES - Real Radius Check")
|
||||
print("=" * 70)
|
||||
print(f"{'Name':<20} {'Type':<15} {'Real Radius (km)':>15}")
|
||||
print("-" * 70)
|
||||
|
||||
for body in bodies:
|
||||
radius = body.extra_data.get('real_radius') if body.extra_data else None
|
||||
print(f"{body.name:<20} {body.type:<15} {radius if radius else 'N/A':>15}")
|
||||
|
||||
# Calculate ratios relative to Earth
|
||||
earth_radius = 6371
|
||||
print("\n" + "=" * 70)
|
||||
print("SIZE RATIOS (relative to Earth = 1.0x)")
|
||||
print("=" * 70)
|
||||
|
||||
for body in sorted(bodies, key=lambda b: b.extra_data.get('real_radius', 0) if b.extra_data else 0, reverse=True):
|
||||
if body.extra_data and body.extra_data.get('real_radius'):
|
||||
radius = body.extra_data['real_radius']
|
||||
ratio = radius / earth_radius
|
||||
print(f"{body.name:<20}: {radius:>8.0f} km = {ratio:>6.2f}x Earth")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(check_solar_system())
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Clear all caches to force fresh data"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.services.redis_cache import redis_cache
|
||||
from app.services.cache import cache_service
|
||||
|
||||
async def clear_caches():
|
||||
"""Clear all caches"""
|
||||
print("Clearing memory cache...")
|
||||
cache_service.clear()
|
||||
print("✓ Memory cache cleared")
|
||||
|
||||
print("\nClearing Redis cache...")
|
||||
try:
|
||||
await redis_cache.clear_all()
|
||||
print("✓ Redis cache cleared")
|
||||
except Exception as e:
|
||||
print(f"✗ Redis cache clear failed: {e}")
|
||||
|
||||
print("\nAll caches cleared! Fresh data will be loaded on next request.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(clear_caches())
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import requests
|
||||
|
||||
def clear_cache():
|
||||
url = "http://localhost:8000/api/system/cache/clear"
|
||||
try:
|
||||
response = requests.post(url, timeout=5)
|
||||
print(f"Status: {response.status_code}")
|
||||
print(f"Body: {response.text}")
|
||||
response.raise_for_status()
|
||||
print(f"Cache cleared: {response.json()}")
|
||||
except Exception as e:
|
||||
print(f"Error clearing cache: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
clear_cache()
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Show the complete picture of the sizing problem"""
|
||||
|
||||
print("=" * 90)
|
||||
print("COMPLETE SIZE CALCULATION ANALYSIS")
|
||||
print("=" * 90)
|
||||
|
||||
# Real radii (km)
|
||||
real_radii = {
|
||||
'Sun': 696000,
|
||||
'Jupiter': 69911,
|
||||
'Saturn': 58232,
|
||||
'Earth': 6371,
|
||||
'Ceres': 476,
|
||||
'Pluto': 1188,
|
||||
}
|
||||
|
||||
# Current config
|
||||
planet_ratio = 0.00008
|
||||
dwarf_ratio = 0.00015
|
||||
star_ratio = 0.0000015
|
||||
|
||||
# Current TYPE_SIZES fallback
|
||||
type_sizes = {
|
||||
'planet': 0.6,
|
||||
'dwarf_planet': 0.18,
|
||||
'star': 0.4,
|
||||
}
|
||||
|
||||
print("\n📊 CURRENT SITUATION:")
|
||||
print("-" * 90)
|
||||
print(f"{'Body':<15} {'Has real_radius?':<20} {'Calculation':<40} {'Size':<10}")
|
||||
print("-" * 90)
|
||||
|
||||
# Planets with real_radius
|
||||
for name in ['Jupiter', 'Saturn', 'Earth']:
|
||||
radius = real_radii[name]
|
||||
size = radius * planet_ratio
|
||||
calc = f"{radius} * {planet_ratio} = {size:.4f}"
|
||||
print(f"{name:<15} {'YES (✓)':<20} {calc:<40} {size:<10.4f}")
|
||||
|
||||
# Dwarf planets WITHOUT real_radius (using fallback)
|
||||
for name in ['Ceres', 'Pluto']:
|
||||
radius = real_radii[name]
|
||||
fallback_size = type_sizes['dwarf_planet']
|
||||
correct_size = radius * planet_ratio # What it SHOULD be
|
||||
calc = f"FALLBACK: {fallback_size:.2f} (should be {correct_size:.4f})"
|
||||
ratio = fallback_size / correct_size
|
||||
print(f"{name:<15} {'NO (✗) MISSING!':<20} {calc:<40} {fallback_size:<10.2f} ({ratio:.1f}x too large!)")
|
||||
|
||||
# Sun WITHOUT real_radius
|
||||
name = 'Sun'
|
||||
radius = real_radii[name]
|
||||
fallback_size = type_sizes['star']
|
||||
correct_size = radius * star_ratio
|
||||
calc = f"FALLBACK: {fallback_size:.2f} (should be {correct_size:.4f})"
|
||||
ratio = fallback_size / correct_size
|
||||
print(f"{name:<15} {'NO (✗) MISSING!':<20} {calc:<40} {fallback_size:<10.2f}")
|
||||
|
||||
print("\n" + "=" * 90)
|
||||
print("⚠️ PROBLEMS:")
|
||||
print("=" * 90)
|
||||
print("1. Dwarf planets (Ceres, Pluto, etc.) use FIXED fallback size 0.18")
|
||||
print(" → Ceres (476 km) should be 0.0381 but shows as 0.18 (4.7x too large!)")
|
||||
print(" → Pluto (1188 km) should be 0.0950 but shows as 0.18 (1.9x too large!)")
|
||||
print()
|
||||
print("2. Different ratios for different types causes MORE confusion:")
|
||||
print(f" → planet ratio: {planet_ratio}")
|
||||
print(f" → dwarf_planet ratio: {dwarf_ratio} (1.875x larger!)")
|
||||
print()
|
||||
print("3. Sun has no real_radius, uses fixed size 0.4")
|
||||
print()
|
||||
|
||||
print("=" * 90)
|
||||
print("✅ SOLUTION:")
|
||||
print("=" * 90)
|
||||
print("1. Add missing real_radius data for:")
|
||||
print(" • Sun: 696000 km")
|
||||
print(" • Ceres: 476 km")
|
||||
print(" • Pluto: 1188 km")
|
||||
print(" • Eris: 1163 km")
|
||||
print(" • Haumea: 816 km")
|
||||
print(" • Makemake: 715 km")
|
||||
print()
|
||||
print("2. Use UNIFIED ratio for all types:")
|
||||
print(" • Recommended: 0.00008 for ALL types (star, planet, dwarf_planet, etc.)")
|
||||
print(" • This ensures consistent scaling based on real physical size")
|
||||
print()
|
||||
print("3. If planets appear too large visually, adjust the GLOBAL ratio:")
|
||||
print(" • Reduce ratio to 0.00005 or 0.00004 for ALL types")
|
||||
print(" • This keeps relative sizes correct while fitting better on screen")
|
||||
print("=" * 90)
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Direct update celestial_type_configs using SQL"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from sqlalchemy import select, update
|
||||
from app.models.db.system_settings import SystemSettings
|
||||
|
||||
# Unified ratio for all types
|
||||
UNIFIED_RATIO = 0.00008
|
||||
|
||||
async def direct_update():
|
||||
"""Direct SQL update of celestial_type_configs"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get the setting record
|
||||
stmt = select(SystemSettings).where(SystemSettings.key == 'celestial_type_configs')
|
||||
result = await session.execute(stmt)
|
||||
setting = result.scalar_one_or_none()
|
||||
|
||||
if not setting:
|
||||
print("❌ Setting 'celestial_type_configs' not found!")
|
||||
return
|
||||
|
||||
# Parse the JSON value
|
||||
current_value = json.loads(setting.value) if isinstance(setting.value, str) else setting.value
|
||||
|
||||
print("BEFORE UPDATE:")
|
||||
print(json.dumps(current_value, indent=2))
|
||||
|
||||
# Update all ratios
|
||||
updated_config = {}
|
||||
for body_type, config in current_value.items():
|
||||
updated_config[body_type] = {
|
||||
'ratio': UNIFIED_RATIO,
|
||||
'default': config.get('default', 0.5)
|
||||
}
|
||||
|
||||
# Update the raw_value (stored as JSON string)
|
||||
setting.raw_value = json.dumps(updated_config)
|
||||
|
||||
await session.commit()
|
||||
|
||||
print("\nAFTER UPDATE:")
|
||||
print(json.dumps(updated_config, indent=2))
|
||||
print(f"\n✅ Successfully updated all ratios to {UNIFIED_RATIO}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(direct_update())
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Verify final sizes after updates - SIMPLIFIED"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from sqlalchemy import select
|
||||
from app.models.db.celestial_body import CelestialBody
|
||||
from app.services.system_settings_service import system_settings_service
|
||||
|
||||
async def verify_final():
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get updated config
|
||||
configs = await system_settings_service.get_setting_value('celestial_type_configs', session)
|
||||
|
||||
# Solar System body IDs
|
||||
solar_ids = ['10', '199', '299', '399', '499', '599', '699', '799', '899', '999',
|
||||
'2000001', '136199', '136108', '136472']
|
||||
|
||||
stmt = select(CelestialBody).where(CelestialBody.id.in_(solar_ids))
|
||||
result = await session.execute(stmt)
|
||||
bodies = result.scalars().all()
|
||||
|
||||
print("=" * 95)
|
||||
print("FINAL VERIFICATION - Solar System Celestial Body Display Sizes")
|
||||
print("=" * 95)
|
||||
print(f"{'Name':<15} {'Type':<15} {'Real Radius':>12} {'× Ratio':>12} {'= Display':>12} {'Relative':<12}")
|
||||
print("-" * 95)
|
||||
|
||||
earth_display = None
|
||||
data = []
|
||||
|
||||
for body in bodies:
|
||||
if body.extra_data and body.extra_data.get('real_radius'):
|
||||
real_radius = body.extra_data['real_radius']
|
||||
ratio = configs[body.type]['ratio']
|
||||
display_size = real_radius * ratio
|
||||
|
||||
data.append({
|
||||
'name': body.name,
|
||||
'type': body.type,
|
||||
'real_radius': real_radius,
|
||||
'ratio': ratio,
|
||||
'display': display_size
|
||||
})
|
||||
|
||||
if body.name == 'Earth':
|
||||
earth_display = display_size
|
||||
|
||||
# Sort by display size
|
||||
data.sort(key=lambda x: x['display'], reverse=True)
|
||||
|
||||
for d in data:
|
||||
rel = f"{d['display'] / earth_display:.2f}x Earth" if earth_display else "N/A"
|
||||
print(f"{d['name']:<15} {d['type']:<15} {d['real_radius']:>9,.0f} km {d['ratio']:.6f} {d['display']:>10.4f} {rel:<12}")
|
||||
|
||||
print("\n" + "=" * 95)
|
||||
print("🎉 SUCCESS! All sizes are now physically accurate and consistent!")
|
||||
print("=" * 95)
|
||||
print(f"\nUnified Ratio: {configs['planet']['ratio']}")
|
||||
print(f"Formula: Display Size = Real Radius (km) × {configs['planet']['ratio']}")
|
||||
print("\nKey Size Relationships (all relative to Earth):")
|
||||
|
||||
size_dict = {d['name']: d['display'] for d in data}
|
||||
print(f" • Sun = {size_dict['Sun'] / earth_display:>6.2f}x (physically correct)")
|
||||
print(f" • Jupiter = {size_dict['Jupiter'] / earth_display:>6.2f}x (should be ~11x) ✓")
|
||||
print(f" • Saturn = {size_dict['Saturn'] / earth_display:>6.2f}x (should be ~9x) ✓")
|
||||
print(f" • Earth = {size_dict['Earth'] / earth_display:>6.2f}x (baseline)")
|
||||
print(f" • Pluto = {size_dict['Pluto'] / earth_display:>6.2f}x (should be ~0.19x) ✓")
|
||||
print(f" • Ceres = {size_dict['Ceres'] / earth_display:>6.2f}x (should be ~0.07x) ✓")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(verify_final())
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test script to verify extra_data in API response"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
# Add backend to path
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.services.db_service import celestial_body_service
|
||||
|
||||
async def test_api_data():
|
||||
"""Simulate API response building"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get Earth
|
||||
body = await celestial_body_service.get_body_by_id("399", session)
|
||||
|
||||
if not body:
|
||||
print("Earth not found in database")
|
||||
return
|
||||
|
||||
# Build response dict like API does
|
||||
body_dict = {
|
||||
"id": body.id,
|
||||
"name": body.name,
|
||||
"name_zh": body.name_zh,
|
||||
"type": body.type,
|
||||
"description": body.description,
|
||||
"is_active": body.is_active,
|
||||
"extra_data": body.extra_data,
|
||||
"positions": []
|
||||
}
|
||||
|
||||
print("=== Database Body Object ===")
|
||||
print(f"Body ID: {body.id}")
|
||||
print(f"Body Name: {body.name}")
|
||||
print(f"Body Type: {body.type}")
|
||||
print(f"Extra Data Type: {type(body.extra_data)}")
|
||||
print(f"Extra Data: {body.extra_data}")
|
||||
|
||||
print("\n=== API Response Dict ===")
|
||||
print(json.dumps(body_dict, indent=2, default=str))
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_api_data())
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Direct API test - simulate the exact API call"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.services.db_service import celestial_body_service, position_service
|
||||
|
||||
async def simulate_api_call():
|
||||
"""Simulate /celestial/positions endpoint"""
|
||||
async with AsyncSessionLocal() as db:
|
||||
# Get all bodies from database
|
||||
all_bodies = await celestial_body_service.get_all_bodies(db)
|
||||
|
||||
# Filter to only Solar System bodies
|
||||
all_bodies = [b for b in all_bodies if b.system_id == 1]
|
||||
|
||||
# Filter to Earth only
|
||||
all_bodies = [b for b in all_bodies if b.id == "399"]
|
||||
|
||||
bodies_data = []
|
||||
now = datetime.utcnow()
|
||||
|
||||
for body in all_bodies:
|
||||
# Get most recent position
|
||||
recent_positions = await position_service.get_positions(
|
||||
body_id=body.id,
|
||||
start_time=now,
|
||||
end_time=now,
|
||||
session=db
|
||||
)
|
||||
|
||||
if recent_positions and len(recent_positions) > 0:
|
||||
latest_pos = recent_positions[-1]
|
||||
body_dict = {
|
||||
"id": body.id,
|
||||
"name": body.name,
|
||||
"name_zh": body.name_zh,
|
||||
"type": body.type,
|
||||
"description": body.description,
|
||||
"is_active": body.is_active,
|
||||
"extra_data": body.extra_data, # THIS IS THE KEY LINE
|
||||
"positions": [{
|
||||
"time": latest_pos.time.isoformat(),
|
||||
"x": latest_pos.x,
|
||||
"y": latest_pos.y,
|
||||
"z": latest_pos.z,
|
||||
}]
|
||||
}
|
||||
bodies_data.append(body_dict)
|
||||
|
||||
print("=== Simulated API Response for Earth ===")
|
||||
print(f"ID: {body_dict['id']}")
|
||||
print(f"Name: {body_dict['name']}")
|
||||
print(f"Type: {body_dict['type']}")
|
||||
print(f"Extra Data: {body_dict['extra_data']}")
|
||||
print(f"Extra Data Type: {type(body_dict['extra_data'])}")
|
||||
if body_dict['extra_data']:
|
||||
print(f"Real Radius: {body_dict['extra_data'].get('real_radius')}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(simulate_api_call())
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Update celestial_type_configs to use unified ratio"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from app.services.system_settings_service import system_settings_service
|
||||
|
||||
# Unified ratio for all types
|
||||
# This ensures consistent scaling based on real physical size
|
||||
UNIFIED_RATIO = 0.00008
|
||||
|
||||
async def update_unified_ratio():
|
||||
"""Update all type ratios to use unified value"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get current config
|
||||
current_config = await system_settings_service.get_setting_value('celestial_type_configs', session)
|
||||
|
||||
print("=" * 70)
|
||||
print("CURRENT celestial_type_configs:")
|
||||
print("=" * 70)
|
||||
print(json.dumps(current_config, indent=2))
|
||||
|
||||
# Update all ratios to unified value
|
||||
updated_config = {}
|
||||
for body_type, config in current_config.items():
|
||||
updated_config[body_type] = {
|
||||
'ratio': UNIFIED_RATIO,
|
||||
'default': config.get('default', 0.5) # Keep existing defaults
|
||||
}
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print(f"UPDATED celestial_type_configs (unified ratio = {UNIFIED_RATIO}):")
|
||||
print("=" * 70)
|
||||
print(json.dumps(updated_config, indent=2))
|
||||
|
||||
# Save updated config
|
||||
await system_settings_service.update_setting(
|
||||
'celestial_type_configs',
|
||||
updated_config,
|
||||
session
|
||||
)
|
||||
|
||||
await session.commit()
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("✅ All type ratios unified successfully!")
|
||||
print("=" * 70)
|
||||
print("\nNOW ALL BODIES WILL USE:")
|
||||
print(f" Display Size = real_radius (km) × {UNIFIED_RATIO}")
|
||||
print("\nThis ensures:")
|
||||
print(" • Consistent scaling across all body types")
|
||||
print(" • Jupiter is correctly 10.97x larger than Earth")
|
||||
print(" • Ceres is correctly 0.07x the size of Earth")
|
||||
print(" • Pluto is correctly 0.19x the size of Earth")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(update_unified_ratio())
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Verify final sizes after updates"""
|
||||
import asyncio
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.join(os.getcwd(), "backend"))
|
||||
|
||||
from app.database import AsyncSessionLocal
|
||||
from sqlalchemy import select
|
||||
from app.models.db.celestial_body import CelestialBody
|
||||
from app.services.system_settings_service import system_settings_service
|
||||
|
||||
async def verify_final_sizes():
|
||||
async with AsyncSessionLocal() as session:
|
||||
# Get updated config
|
||||
configs = await system_settings_service.get_setting_value('celestial_type_configs', session)
|
||||
|
||||
# Solar System body IDs
|
||||
solar_ids = ['10', '199', '299', '399', '499', '599', '699', '799', '899', '999',
|
||||
'2000001', '136199', '136108', '136472']
|
||||
|
||||
stmt = select(CelestialBody).where(CelestialBody.id.in_(solar_ids))
|
||||
result = await session.execute(stmt)
|
||||
bodies = result.scalars().all()
|
||||
|
||||
print("=" * 85)
|
||||
print("FINAL VERIFICATION - All Celestial Body Sizes")
|
||||
print("=" * 85)
|
||||
print(f"{'Name':<20} {'Type':<15} {'Real Radius':<15} {'Ratio':<12} {'Display Size':<12} {'vs Earth'}")
|
||||
print("-" * 85)
|
||||
|
||||
earth_size = None
|
||||
sizes = []
|
||||
|
||||
for body in sorted(bodies, key=lambda b: b.extra_data.get('real_radius', 0) if b.extra_data else 0, reverse=True):
|
||||
if body.extra_data and body.extra_data.get('real_radius'):
|
||||
real_radius = body.extra_data['real_radius']
|
||||
ratio = configs[body.type]['ratio']
|
||||
display_size = real_radius * ratio
|
||||
|
||||
sizes.append((body.name, body.type, real_radius, ratio, display_size))
|
||||
|
||||
if body.name == 'Earth':
|
||||
earth_size = display_size
|
||||
|
||||
# Print with Earth comparison
|
||||
for name, btype, real_radius, ratio, display_size in sizes:
|
||||
vs_earth = f"{display_size / earth_size:.2f}x" if earth_size else "N/A"
|
||||
print(f"{name:<20} {btype:<15} {real_radius:>8.0f} km {ratio:.6f} {display_size:>10.4f} {vs_earth:>7}")
|
||||
|
||||
print("\n" + "=" * 85)
|
||||
print("✅ VERIFICATION COMPLETE")
|
||||
print("=" * 85)
|
||||
print("All bodies now use:")
|
||||
print(f" • Unified ratio: {configs['planet']['ratio']}")
|
||||
print(f" • Display Size = real_radius × {configs['planet']['ratio']}")
|
||||
print("\nSize relationships:")
|
||||
print(f" • Jupiter = {sizes[0][4] / earth_size:.2f}x Earth (should be ~11x)")
|
||||
print(f" • Saturn = {sizes[1][4] / earth_size:.2f}x Earth (should be ~9x)")
|
||||
print(f" • Pluto = {[s for s in sizes if s[0] == 'Pluto'][0][4] / earth_size:.2f}x Earth (should be ~0.19x)")
|
||||
print(f" • Ceres = {[s for s in sizes if s[0] == 'Ceres'][0][4] / earth_size:.2f}x Earth (should be ~0.07x)")
|
||||
print("\n🎉 All sizes are now consistent and physically accurate!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(verify_final_sizes())
|
||||
Loading…
Reference in New Issue