Files
KG_generation/equipment_calculation/calculator_base.py
T
chentianrui 9609bb67b4 上传文件
2025-08-01 15:31:56 +08:00

241 lines
8.6 KiB
Python

import os
from abc import ABC, abstractmethod
from typing import Dict, List, Any, Optional, Tuple
from software_types import SoftwareType
from find_project_nodes import get_project_divisions_list
from quantity_fee_calculator import calculate_quantity_fees as base_calculate_quantity_fees
from resource_fee_calculator import calculate_resource_fees as base_calculate_resource_fees
from calculation_strategy import CalculationStrategy, DefaultCalculationStrategy
import json
class CalculatorBase(ABC):
"""计算器基类"""
def __init__(self, software_type: SoftwareType):
"""
初始化计算器
Args:
software_type: 软件类型
"""
self.software_type = software_type
self.config_dir = software_type.config_dir
# 使用默认计算策略
self.calculation_strategy = self.create_calculation_strategy()
def create_calculation_strategy(self) -> CalculationStrategy:
"""
创建计算策略
子类可以重写此方法,返回特定的计算策略实现
Returns:
CalculationStrategy: 计算策略实例
"""
return DefaultCalculationStrategy()
def get_default_input_file(self) -> str:
"""获取默认输入文件路径"""
return os.path.join(self.software_type.test_dir)
def get_output_dir(self) -> str:
"""获取输出目录路径"""
base_dir = "计算结果"
return os.path.join(base_dir, self.software_type.name)
def calculate_quantity_fee_tables(
self,
json_file_path: str,
project_name: str = None,
) -> None:
"""
计算工程量取费表
Args:
json_file_path: JSON文件路径
project_name: 项目名称,如果为None则处理所有项目
"""
engineering_type = self.software_type.engineering_type.value + "工程"
# 在计算前应用软件特定的规则
preprocess_func = self.apply_quantity_fee_rules()
if callable(preprocess_func): # 检查返回值是否可调用
preprocess_func(json_file_path) # 调用预处理函数
if project_name:
# 处理单个项目划分
print(f"处理单个项目划分: {project_name}")
output_file = self._calculate_quantity_fees(json_file_path, project_name, engineering_type)
if output_file:
print(f"已完成 {project_name} 的工程量取费表计算,结果保存在 {output_file}")
else:
# 处理所有项目划分
project_divisions = get_project_divisions_list(json_file_path)
print(f"找到 {len(project_divisions)} 个项目划分节点,开始处理工程量取费表...")
for i, (proj_name, proj_guid) in enumerate(project_divisions, 1):
# 使用命令行参数中指定的调差类型,而不是从JSON文件中获取的调差类型
print(f"处理 {i}/{len(project_divisions)}: {proj_name} (GUID: {proj_guid})")
output_file = self._calculate_quantity_fees(json_file_path, proj_name, engineering_type, proj_guid)
if output_file:
print(f"已完成 {proj_name} (GUID: {proj_guid}) 的工程量取费表计算")
print(f"所有项目划分节点的工程量取费表计算完成,结果保存在 {self.get_output_dir()} 目录")
def calculate_resource_fee_tables(self, json_file_path: str, project_name: str = None) -> None:
"""
计算人材机合价
Args:
json_file_path: JSON文件路径
project_name: 项目名称,如果为None则处理所有项目
"""
# 获取工程类型
engineering_type = self.software_type.engineering_type.value + "工程"
# 在计算前应用软件特定的规则
self.apply_resource_fee_rules()
if project_name:
# 处理单个项目划分
output_file = self._calculate_resource_fees(
json_file_path,
project_name,
)
if output_file:
print(f"已完成 {project_name} 的人材机合价计算,结果保存在 {output_file}")
else:
# 处理所有项目划分
project_divisions = get_project_divisions_list(json_file_path)
print(f"找到 {len(project_divisions)} 个项目划分节点,开始处理人材机合价...")
for i, (proj_name, proj_guid) in enumerate(project_divisions, 1):
print(f"处理 {i}/{len(project_divisions)}: {proj_name} (GUID: {proj_guid})")
output_file = self._calculate_resource_fees(json_file_path, proj_name, proj_guid)
if output_file:
print(f"已完成 {proj_name} (GUID: {proj_guid}) 的人材机合价计算")
print(f"所有项目划分节点的人材机合价计算完成,结果保存在 {self.get_output_dir()} 目录")
def _calculate_quantity_fees(
self,
json_file_path: str,
project_name: str,
engineering_type: str,
project_guid: str = None,
) -> str:
"""
计算工程量取费表,并应用软件特定的后处理规则
Args:
json_file_path: JSON文件路径
project_name: 项目名称
engineering_type: 工程类型
project_guid: 项目GUID,用于区分同名项目
Returns:
str: 输出文件路径
"""
# 确保输出目录存在
os.makedirs(self.get_output_dir(), exist_ok=True)
# 初始化BCL计算器,传递软件类型和计算类型
from bcl_utils import init_bcl_calculator
init_bcl_calculator(
software_category=self.software_type.category.value,
engineering_type=self.software_type.engineering_type.value,
calculation_type="工程量",
)
# 打印计算策略信息
print(f"使用计算策略: {self.calculation_strategy.__class__.__name__}")
# 调用基础计算函数,传入计算策略和项目GUID
output_file = base_calculate_quantity_fees(
json_file_path,
project_name,
engineering_type,
project_guid=project_guid,
calculation_strategy=self.calculation_strategy,
)
# 应用软件特定的后处理规则
if output_file:
self.post_process_quantity_fees(output_file, project_name)
return output_file
def _calculate_resource_fees(
self,
json_file_path: str,
project_name: str,
project_guid: str = None,
) -> str:
"""
计算人材机合价,并应用软件特定的后处理规则
Args:
json_file_path: JSON文件路径
project_name: 项目名称
engineering_type: 工程类型
project_guid: 项目GUID,用于区分同名项目
Returns:
str: 输出文件路径
"""
# 确保输出目录存在
os.makedirs(self.get_output_dir(), exist_ok=True)
# 初始化BCL计算器,传递软件类型和计算类型
from bcl_utils import init_bcl_calculator
init_bcl_calculator(
software_category=self.software_type.category.value,
engineering_type=self.software_type.engineering_type.value,
calculation_type="人材机",
)
# 调用基础计算函数,传入计算策略和项目GUID
output_file = base_calculate_resource_fees(
json_file_path,
project_name,
project_guid=project_guid,
calculation_strategy=self.calculation_strategy,
)
# 应用软件特定的后处理规则
if output_file:
self.post_process_resource_fees(output_file, project_name)
return output_file
def apply_quantity_fee_rules(self) -> None:
"""应用软件特定的工程量取费规则(在计算前)"""
pass
def apply_resource_fee_rules(self) -> None:
"""应用软件特定的人材机合价规则(在计算前)"""
pass
def post_process_quantity_fees(self, output_file: str, project_name: str) -> None:
"""
应用软件特定的工程量取费后处理规则
Args:
output_file: 输出文件路径
project_name: 项目名称
"""
pass
def post_process_resource_fees(self, output_file: str, project_name: str) -> None:
"""
应用软件特定的人材机合价后处理规则
Args:
output_file: 输出文件路径
project_name: 项目名称
"""
pass