1.修改工况推理,把冬休情况加入
This commit is contained in:
@@ -9,6 +9,7 @@ class OperatingModePredictor:
|
||||
2. 输出为一维列表,仅保留每个内嵌列表的最新记录,新增工况推导结果字段
|
||||
3. 无需切换工况时,next_workinfo返回当前工况名称;需要切换时返回目标工况名称
|
||||
4. 时间计算仅按日期(天)维度,忽略时分秒
|
||||
5. 支持冬休场景:当前工况为冬休时,以冬休前上一个有效工况作为切换判断依据
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
@@ -19,6 +20,8 @@ class OperatingModePredictor:
|
||||
self.condition_group = self._load_condition_group()
|
||||
# 工况切换触发规则(键:分组ID,值:触发天数+目标工况候选)
|
||||
self.group_transition_rules = self._load_group_transition_rules()
|
||||
# 冬休工况标识(仅保留“冬休”)
|
||||
self.winter_break_labels = self._load_winter_break_labels()
|
||||
|
||||
def _load_base_periods(self):
|
||||
"""加载基础工况配置(私有方法,内部使用)"""
|
||||
@@ -62,12 +65,13 @@ class OperatingModePredictor:
|
||||
"架桥机(运梁车) 首次通过后": 7,
|
||||
"轨道板(道床)铺设后,第1个月": 14,
|
||||
"轨道板(道床)铺设后,第2至3个月": 30,
|
||||
"轨道板(道床)铺设后,3个月以后": 90
|
||||
"轨道板(道床)铺设后,3个月以后": 90,
|
||||
"冬休": 0 # 仅保留冬休
|
||||
}
|
||||
|
||||
def _load_condition_group(self):
|
||||
"""加载工况分组规则(私有方法,内部使用)"""
|
||||
return {
|
||||
condition_group = {
|
||||
"仰拱(底板)施工完成后,第1个月": "YG_DIBAN_1",
|
||||
"仰拱(底板)施工完成后,第1个月": "YG_DIBAN_1",
|
||||
"仰拱(底板)施工完成后,第2至3个月": "YG_DIBAN_2_3",
|
||||
@@ -109,6 +113,12 @@ class OperatingModePredictor:
|
||||
"填筑或堆载,两次填筑间隔时间较长情况": "STATIC",
|
||||
"铺路或堆载,两次铺路间隔时间较长情况": "STATIC"
|
||||
}
|
||||
# 冬休分组(仅冬休)
|
||||
winter_break_groups = {
|
||||
"冬休": "STATIC"
|
||||
}
|
||||
condition_group.update(winter_break_groups)
|
||||
return condition_group
|
||||
|
||||
def _load_group_transition_rules(self):
|
||||
"""加载工况切换触发规则(私有方法,内部使用)"""
|
||||
@@ -140,6 +150,10 @@ class OperatingModePredictor:
|
||||
"STATIC": {"trigger_days": None, "next_candidates": None}
|
||||
}
|
||||
|
||||
def _load_winter_break_labels(self):
|
||||
"""冬休标识(仅冬休)"""
|
||||
return {"冬休"}
|
||||
|
||||
def _parse_to_date(self, time_str):
|
||||
"""
|
||||
私有辅助方法:将时间字符串解析为日期对象,仅保留年月日,忽略时分秒
|
||||
@@ -158,54 +172,68 @@ class OperatingModePredictor:
|
||||
"""
|
||||
私有辅助方法:从倒序数据中提取时间统计信息
|
||||
:param data: 单个point_id的倒序数据列表
|
||||
:param workinfo: 当前工况名称
|
||||
:param workinfo: 目标工况名称(冬休时为冬休前上一工况)
|
||||
:return: 元组 (首次测量日期date对象, 首次到末次持续天数, 今日与首次测量天数差)
|
||||
"""
|
||||
# 筛选当前工况的有效记录
|
||||
reversed_records = [d for d in data if d.get("workinfoname") == workinfo]
|
||||
if not reversed_records:
|
||||
# 筛选目标工况的有效记录(忽略冬休)
|
||||
target_records = [
|
||||
d for d in data
|
||||
if d.get("workinfoname") == workinfo
|
||||
and d.get("workinfoname") not in self.winter_break_labels
|
||||
]
|
||||
if not target_records:
|
||||
return None, 0, 0
|
||||
|
||||
# 解析所有有效记录的日期
|
||||
reversed_dates = []
|
||||
for item in reversed_records:
|
||||
target_dates = []
|
||||
for item in target_records:
|
||||
d = self._parse_to_date(item.get("MTIME_W"))
|
||||
if d:
|
||||
reversed_dates.append(d)
|
||||
if not reversed_dates:
|
||||
target_dates.append(d)
|
||||
if not target_dates:
|
||||
return None, 0, 0
|
||||
|
||||
# 提取倒序数据的最新、最旧日期
|
||||
last_date = reversed_dates[0]
|
||||
first_date = reversed_dates[-1]
|
||||
last_date = target_dates[0]
|
||||
first_date = target_dates[-1]
|
||||
|
||||
# 计算累计天数和今日与首次测量的天数差
|
||||
cumulative_days = (last_date - first_date).days
|
||||
today = date.today()
|
||||
days_to_today = (today - first_date).days if first_date else 0
|
||||
|
||||
return first_date, cumulative_days, days_to_today
|
||||
|
||||
def _get_pre_winter_break_workinfo(self, inner_data_list):
|
||||
"""
|
||||
私有辅助方法:从倒序数据中提取冬休前的上一个有效工况
|
||||
:param inner_data_list: 单个point_id的倒序数据列表
|
||||
:return: 冬休前工况名称 / None(未找到时)
|
||||
"""
|
||||
if not inner_data_list:
|
||||
return None
|
||||
|
||||
# 倒序遍历,跳过冬休,找第一个有效工况
|
||||
for record in inner_data_list:
|
||||
current_work = record.get("workinfoname")
|
||||
if current_work and current_work not in self.winter_break_labels and current_work in self.base_periods:
|
||||
return current_work
|
||||
return None
|
||||
|
||||
def _match_next_condition(self, current_name, candidates):
|
||||
"""
|
||||
私有辅助方法:按符号风格匹配下一个工况名称(全角/半角括号对应)
|
||||
:param current_name: 当前工况名称
|
||||
:param current_name: 当前工况名称(冬休时为冬休前上一工况)
|
||||
:param candidates: 目标工况候选列表
|
||||
:return: 匹配的工况名称 / 当前工况名称(无候选时)
|
||||
"""
|
||||
if not candidates:
|
||||
return current_name
|
||||
# 优先匹配全角括号工况
|
||||
if "(" in current_name:
|
||||
for cand in candidates:
|
||||
if "(" in cand:
|
||||
return cand
|
||||
# 再匹配半角括号工况
|
||||
if "(" in current_name:
|
||||
for cand in candidates:
|
||||
if "(" in cand:
|
||||
return cand
|
||||
# 无对应符号时,返回第一个候选工况
|
||||
return candidates[0]
|
||||
|
||||
def _validate_point_id(self, inner_list):
|
||||
@@ -230,17 +258,13 @@ class OperatingModePredictor:
|
||||
"""
|
||||
final_result_1d = []
|
||||
|
||||
# 遍历二维列表,逐个处理每个point_id的内嵌数据
|
||||
for inner_data_list in data_2d_list:
|
||||
# 跳过空列表
|
||||
if not isinstance(inner_data_list, list) or len(inner_data_list) == 0:
|
||||
continue
|
||||
|
||||
# 1. 提取当前内嵌列表的最新记录(倒序数据索引0为最新)
|
||||
latest_record = inner_data_list[0].copy()
|
||||
|
||||
# 2. 校验point_id一致性
|
||||
point_id = self._validate_point_id(inner_data_list)
|
||||
|
||||
if not point_id:
|
||||
latest_record.update({
|
||||
"status": "fail",
|
||||
@@ -248,12 +272,12 @@ class OperatingModePredictor:
|
||||
"first_measure_date": None,
|
||||
"days_from_first_to_today": None,
|
||||
"next_workinfo": None,
|
||||
"judge_based_workinfo": None,
|
||||
"error_msg": "point_id不一致或缺失"
|
||||
})
|
||||
final_result_1d.append(latest_record)
|
||||
continue
|
||||
|
||||
# 3. 提取并校验当前工况
|
||||
current_workinfo = latest_record.get("workinfoname")
|
||||
if not current_workinfo or current_workinfo not in self.base_periods:
|
||||
latest_record.update({
|
||||
@@ -262,41 +286,59 @@ class OperatingModePredictor:
|
||||
"first_measure_date": None,
|
||||
"days_from_first_to_today": None,
|
||||
"next_workinfo": None,
|
||||
"judge_based_workinfo": None,
|
||||
"error_msg": "工况无效或缺失"
|
||||
})
|
||||
final_result_1d.append(latest_record)
|
||||
continue
|
||||
|
||||
# 4. 提取时间统计信息
|
||||
# 冬休逻辑:当前是冬休 → 取冬休前工况作为判断基准
|
||||
if current_workinfo in self.winter_break_labels:
|
||||
judge_based_workinfo = self._get_pre_winter_break_workinfo(inner_data_list)
|
||||
if not judge_based_workinfo:
|
||||
latest_record.update({
|
||||
"status": "fail",
|
||||
"current_workinfo": current_workinfo,
|
||||
"first_measure_date": None,
|
||||
"days_from_first_to_today": None,
|
||||
"next_workinfo": None,
|
||||
"judge_based_workinfo": None,
|
||||
"error_msg": "冬休前未找到有效工况"
|
||||
})
|
||||
final_result_1d.append(latest_record)
|
||||
continue
|
||||
else:
|
||||
judge_based_workinfo = current_workinfo
|
||||
|
||||
# 用判断基准工况计算时间
|
||||
first_dt, cumulative_days, days_to_today = self._get_time_statistics_from_reversed(
|
||||
inner_data_list, current_workinfo
|
||||
inner_data_list, judge_based_workinfo
|
||||
)
|
||||
first_measure_date = first_dt.strftime("%Y-%m-%d") if first_dt else None
|
||||
|
||||
# 5. 判断工况切换条件,推导下一工况
|
||||
group_id = self.condition_group.get(current_workinfo, "STATIC")
|
||||
# 推导下一工况
|
||||
group_id = self.condition_group.get(judge_based_workinfo, "STATIC")
|
||||
rule = self.group_transition_rules.get(group_id, {})
|
||||
trigger_days = rule.get("trigger_days")
|
||||
next_candidates = rule.get("next_candidates", [])
|
||||
|
||||
if trigger_days is not None and cumulative_days >= trigger_days:
|
||||
# 满足切换条件:返回目标工况
|
||||
next_workname = self._match_next_condition(current_workinfo, next_candidates)
|
||||
next_workname = self._match_next_condition(judge_based_workinfo, next_candidates)
|
||||
else:
|
||||
# 不满足切换条件:返回当前工况
|
||||
next_workname = current_workinfo
|
||||
next_workname = judge_based_workinfo
|
||||
|
||||
# 6. 组装结果字段,更新最新记录
|
||||
# 组装结果
|
||||
latest_record.update({
|
||||
"status": "success",
|
||||
"current_workinfo": current_workinfo,
|
||||
"judge_based_workinfo": judge_based_workinfo,
|
||||
"first_measure_date": first_measure_date,
|
||||
"days_from_first_to_today": days_to_today,
|
||||
"next_workinfo": next_workname,
|
||||
"point_id": point_id
|
||||
"point_id": point_id,
|
||||
"error_msg": ""
|
||||
})
|
||||
|
||||
# 7. 加入最终结果列表
|
||||
final_result_1d.append(latest_record)
|
||||
|
||||
return final_result_1d
|
||||
Reference in New Issue
Block a user