116 lines
3.7 KiB
Python
116 lines
3.7 KiB
Python
"""
|
|
计算所有隐患点的灾害影响范围并填充 xian_hazard_zones 表
|
|
|
|
仅计算隐患点 (xian_hidden_danger_spots),不计算风险点。
|
|
灾害类型包括: 滑坡、泥石流、山洪、内涝、崩塌
|
|
|
|
"""
|
|
import sys
|
|
import os
|
|
from datetime import datetime
|
|
|
|
# 确保项目根目录在 sys.path 中
|
|
_project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
if _project_root not in sys.path:
|
|
sys.path.insert(0, _project_root)
|
|
|
|
from app.utils.logger import LoggerManager
|
|
from app.repositories.hazard_repository import hazard_repository
|
|
from app.models.hazard.hazard_zone_calculator import hazard_zone_calculator
|
|
|
|
_BATCH_SIZE = 200 # 每处理200条输出一次进度
|
|
|
|
logger = LoggerManager.get_logger("hazard_zones",
|
|
os.path.join(_project_root, "logs"))
|
|
|
|
|
|
def main():
|
|
logger.info("=" * 60)
|
|
logger.info("开始计算隐患点灾害影响范围")
|
|
logger.info(f"启动时间: {datetime.now().isoformat()}")
|
|
logger.info("=" * 60)
|
|
|
|
# 1. 获取所有隐患点
|
|
spots = hazard_repository.get_all_hidden_danger_spots()
|
|
total = len(spots)
|
|
logger.info(f"查询到 {total} 个隐患点")
|
|
if total == 0:
|
|
logger.warning("没有隐患点数据,退出")
|
|
return
|
|
|
|
# 按灾害类型统计
|
|
type_counts = {}
|
|
for s in spots:
|
|
dt = s['disaster_type']
|
|
type_counts[dt] = type_counts.get(dt, 0) + 1
|
|
logger.info(f"灾害类型分布: {type_counts}")
|
|
|
|
# 2. 逐点计算
|
|
records = []
|
|
success_count = 0
|
|
skip_count = 0
|
|
error_count = 0
|
|
|
|
for i, spot in enumerate(spots):
|
|
sid = spot['source_id']
|
|
dtype = spot['disaster_type']
|
|
dname = spot['disaster_name']
|
|
scale = spot.get('scale_grade')
|
|
|
|
try:
|
|
zone_wkt, path_wkt = hazard_zone_calculator.calculate(
|
|
source_id=sid,
|
|
disaster_type=dtype,
|
|
scale_grade=scale,
|
|
lon=spot['lon'],
|
|
lat=spot['lat'],
|
|
static_factors=spot['static_factors']
|
|
)
|
|
|
|
if zone_wkt:
|
|
records.append({
|
|
'source_id': sid,
|
|
'disaster_type': dtype,
|
|
'zone_wkt': zone_wkt,
|
|
'path_wkt': path_wkt
|
|
})
|
|
success_count += 1
|
|
else:
|
|
skip_count += 1
|
|
logger.debug(f"跳过 [{sid}] {dname}({dtype}): 无法计算影响范围")
|
|
|
|
except Exception as e:
|
|
error_count += 1
|
|
logger.error(f"计算失败 [{sid}] {dname}({dtype}): {e}")
|
|
|
|
# 进度输出
|
|
if (i + 1) % _BATCH_SIZE == 0 or (i + 1) == total:
|
|
logger.info(f"进度: {i + 1}/{total} "
|
|
f"(成功:{success_count} 跳过:{skip_count} 失败:{error_count})")
|
|
|
|
# 3. 写入数据库
|
|
logger.info(f"计算完成。开始写入数据库,共 {len(records)} 条记录")
|
|
|
|
# 先逻辑删除旧数据
|
|
deleted = hazard_repository.delete_existing_zones()
|
|
logger.info(f"已标记 {deleted} 条旧记录为删除")
|
|
|
|
# 批量写入新数据
|
|
inserted = hazard_repository.batch_insert_zones(records)
|
|
logger.info(f"成功写入 {inserted} 条新记录")
|
|
|
|
# 4. 汇总
|
|
logger.info("=" * 60)
|
|
logger.info("执行完成")
|
|
logger.info(f" 隐患点总数: {total}")
|
|
logger.info(f" 计算成功: {success_count}")
|
|
logger.info(f" 跳过: {skip_count}")
|
|
logger.info(f" 计算失败: {error_count}")
|
|
logger.info(f" 写入记录: {inserted}")
|
|
logger.info(f"完成时间: {datetime.now().isoformat()}")
|
|
logger.info("=" * 60)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|