Files
KG_generation/compare_BclCost.py
T
chentianrui f5f26c5cf8 上传代码
2025-09-08 17:58:02 +08:00

234 lines
8.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import shutil
import time
from pathlib import Path
import traceback
import uuid
import random
import string
import argparse
# 导入各个步骤需要的函数
from project2json.project_converter import convert_project_to_json
from transform_expense_preview import process_directory
from supplement_kg import costsummary_upwards
from equipment_calculation.main import bcl_calculate
from cost_comparison import compare_costs_batch
import tempfile
# 基础目录
BASE_DIR = "project2json"
TEMP_DIR = tempfile.gettempdir() # 使用临时目录
# 生成随机8位ID
def generate_session_id():
return "".join(random.choices(string.ascii_uppercase + string.digits, k=8))
# 创建会话工作目录(仅会话根目录)
def create_session_directories(session_id):
# 仅创建会话根目录用于容纳每个文件的独立GUID临时目录
session_root = os.path.join(BASE_DIR, "outputs", session_id)
os.makedirs(session_root, exist_ok=True)
return {
"session_root": session_root,
}
# 为单个上传文件创建独立的GUID临时目录,包含六个子目录
def create_file_workdirs(session_id):
file_guid = uuid.uuid4().hex
root = os.path.join(BASE_DIR, "outputs", session_id, file_guid)
dirs = {
"root": root,
"upload_dir": os.path.join(root, "uploads"), # 生成json前的上传文件夹
"bcl_dir": os.path.join(root, "bcl"), # bcl计算文件文件夹(备用,当前流程未直接使用)
"json_dir": os.path.join(root, "json"), # 生成后的json文件夹
"merged_dir": os.path.join(root, "merged"),
"bcl_results_dir": os.path.join(root, "bclresults"),
"final_dir": os.path.join(root, "final"),
}
for d in dirs.values():
os.makedirs(d, exist_ok=True)
return dirs
# 整合的转化流程函数(无前端),执行步骤1到步骤3,并将步骤3.2/4替换为 compare_costs_batch
def convert_all_steps(files):
"""处理传入的工程文件列表,输出成功执行的文件数量。
流程:
1) 保存上传 -> 转JSON
2) 处理JSON结构并费用向上汇总(merged_dir)
3) BCL计算(输出到 bcl_results_dir
4) 调用 compare_costs_batch(bcl_results_dir, project_json) 进行费用对比
"""
try:
session_id = generate_session_id()
print(f"生成会话ID: {session_id}")
session_dirs = create_session_directories(session_id)
session_root = session_dirs["session_root"]
total_files = len(files) if files else 0
if total_files == 0:
print("未选择任何文件。")
return 0
total_success = 0
for idx, file in enumerate(files, start=1):
try:
file_name = os.path.basename(file if isinstance(file, str) else file.name)
print(f"[{idx}/{total_files}] 处理文件: {file_name}")
# 创建该文件的独立GUID临时目录
fdirs = create_file_workdirs(session_id)
upload_dir = fdirs["upload_dir"]
json_dir = fdirs["json_dir"]
merged_dir = fdirs["merged_dir"]
bcl_results_dir = fdirs["bcl_results_dir"]
# 步骤1.1: 保存上传的该文件
save_path = os.path.join(upload_dir, file_name)
shutil.copy(file if isinstance(file, str) else file.name, save_path)
# 步骤1.2: 转换为JSON
success, file_num = convert_project_to_json(upload_dir, json_dir, fdirs["bcl_dir"])
if not success:
raise RuntimeError("转换为JSON失败")
# 步骤1.3: 处理JSON文件结构
process_directory(json_dir)
# 步骤2: 费用向上汇总
result_step2 = costsummary_upwards(json_dir, merged_dir)
if not result_step2:
print("警告:未生成任何汇总JSON")
# 步骤3.1: 计算工程量取费表
bcl_calculate(merged_dir, bcl_results_dir, bcl_dir_path=fdirs["bcl_dir"])
# 选择项目JSON:从 merged_dir 中选择一个主 JSON(若多个则取第一个)
merged_jsons = [
os.path.join(merged_dir, f) for f in os.listdir(merged_dir) if f.lower().endswith(".json")
]
if not merged_jsons:
raise FileNotFoundError("在 merged_dir 中未找到项目 JSON")
project_data_json_path = merged_jsons[0]
# 步骤3.2/4: 调用 compare_costs_batch 进行费用对比
compare_costs_batch(bcl_results_dir, project_data_json_path)
total_success += 1
except Exception as fe:
print(f"处理文件 {file_name} 失败: {fe}\n{traceback.format_exc()}")
print(f"成功执行 {total_success} 个文件。")
return total_success
except Exception as e:
error_msg = f"执行流程出错: {str(e)}\n{traceback.format_exc()}"
print(error_msg)
return 0
# ========= 批处理与命令行入口(文件末尾追加) =========
def create_named_workdirs(output_base_dir: str, base_name: str):
"""在输出根目录下创建 '<工程名>+<GUID>' 的工作目录结构。"""
guid = uuid.uuid4().hex
root_name = f"{base_name}+{guid}"
root = os.path.join(output_base_dir, root_name)
dirs = {
"root": root,
"upload_dir": os.path.join(root, "uploads"),
"bcl_dir": os.path.join(root, "bcl"),
"json_dir": os.path.join(root, "json"),
"merged_dir": os.path.join(root, "merged"),
"bcl_results_dir": os.path.join(root, "bclresults"),
"final_dir": os.path.join(root, "final"),
}
for d in dirs.values():
os.makedirs(d, exist_ok=True)
return dirs
def run_batch_with_io(input_dir: str, output_dir: str) -> int:
"""批量处理输入目录下的工程文件,输出到指定的输出根目录。"""
input_dir = os.path.abspath(input_dir)
output_dir = os.path.abspath(output_dir)
os.makedirs(output_dir, exist_ok=True)
candidates = [
os.path.join(input_dir, f) for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))
]
if not candidates:
print(f"输入目录无文件: {input_dir}")
return 0
total_success = 0
for idx, file_path in enumerate(candidates, start=1):
base_name = os.path.basename(file_path)
stem = os.path.splitext(base_name)[0]
print(f"[{idx}/{len(candidates)}] 处理文件: {base_name}")
try:
# 1) 为该工程创建独立工作区
fdirs = create_named_workdirs(output_dir, stem)
upload_dir = fdirs["upload_dir"]
json_dir = fdirs["json_dir"]
merged_dir = fdirs["merged_dir"]
bcl_results_dir = fdirs["bcl_results_dir"]
bcl_dir = fdirs["bcl_dir"]
# 2) 保存上传
save_path = os.path.join(upload_dir, base_name)
shutil.copy(file_path, save_path)
# 3) 转换为JSON(并将 BCL 最佳版本复制到 bcl_dir
success, _file_num = convert_project_to_json(upload_dir, json_dir, bcl_dir)
if not success:
raise RuntimeError("转换为JSON失败")
# 4) 处理JSON结构
process_directory(json_dir)
# 5) 费用向上汇总
result_step2 = costsummary_upwards(json_dir, merged_dir)
if not result_step2:
print("警告:未生成任何汇总JSON")
# 6) 计算工程量取费表(读取 bcl_dir,输出到 bcl_results_dir
bcl_calculate(merged_dir, bcl_results_dir, bcl_dir_path=bcl_dir)
# 7) 选择一个项目 JSON 进行费用对比
merged_jsons = [os.path.join(merged_dir, f) for f in os.listdir(merged_dir) if f.lower().endswith(".json")]
if not merged_jsons:
raise FileNotFoundError("在 merged_dir 中未找到项目 JSON")
project_data_json_path = merged_jsons[0]
# 8) 费用对比
compare_costs_batch(bcl_results_dir, project_data_json_path)
total_success += 1
except Exception as fe:
print(f"处理文件 {base_name} 失败: {fe}\n{traceback.format_exc()}")
print(f"成功执行 {total_success}/{len(candidates)} 个文件。输出根目录: {output_dir}")
return total_success
if __name__ == "__main__":
input_dir = r"data/input" # 请修改为你的实际输入路径
output_dir = r"data/output" # 请修改为你的实际输出路径
t0 = time.time()
try:
count = run_batch_with_io(input_dir, output_dir)
print(f"\n🎉 ✅ 处理完成,共成功 {count} 个。耗时: {int(time.time() - t0)} 秒")
except Exception as e:
print(f"\n❌ 执行失败: {e}\n{traceback.format_exc()}")
raise