重新定义天体大小的展现逻辑
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