- V8 卫生 grep 断言落地 smoke(字符串 Callable 产品码零命中/FeatsEngine 退役/死代码抽查/GP 影子账零残留) - 06 补登卡片两条义务(长函数余量 14 件+lambda 连接 76 处防回归) - 漏网字符串 Callable×2 补装+validator 头注/main 死注记清理 - resolver 幽灵通道断根: reset_warn_dedup 门面参从未存在(字符串 Callable 零校验藏死引用, 方法引用换装编译期暴露)——删参,注册表清空归 resolver 本类方法(门面 :115 直呼即正道) - 实现报告补核对结案段 闸: 冒烟 1086/0(+V8×5)+类型闸归零
126 lines
5.9 KiB
GDScript
126 lines
5.9 KiB
GDScript
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||
# Date: 2026-10-02(code-quality 修复批 T5——ConfigDb 拆分:R1 难度行解析协作类,自 config_db.gd 迁出)
|
||
# 职责单一化(R1 解析域):resolve_board_gen / resolve_enemy_rowset / resolve_difficulty_modifiers
|
||
# 及其私有算术(_resolve_progress / _ceil_key)与 R1 专属的告警去重注册表。ConfigDb autoload 门面
|
||
# 保持——全部消费方(战斗结算/敌人系统/棋盘生成/呈现层/冒烟)经门面同名方法取数,公有签名零变化。
|
||
# 诊断通道归门面:push_diag / _fatal 经 _db 引用回呼(协作类同仓内部通道——不另设公共出口,
|
||
# 行为与拆分前逐位一致,含越域 Fatal 退出语义)。
|
||
# 迁移注记:_warn_dedup 去重注册表随解析逻辑同迁(唯一消费方 = _resolve_progress)——
|
||
# 门面 load_tables / reset_diagnostics 经 reset_warn_dedup() 同步清空,清空时点零变化。
|
||
# 实现 GDD:design/gdd/systems/表现与支撑/数据配置.md(系统 ID D2·数据配置——registry 追溯锚)
|
||
class_name ConfigDbResolver
|
||
extends RefCounted
|
||
|
||
var _diag: Callable # 诊断/致命通道(迭代 27 T6——门面类型反持解耦,validator 先例:签名 (level, category, message))
|
||
var _board_gen_rows_get: Callable # () -> Array——board_gen 行集活读(数据面经 Callable 注入,ConfigDb 类型环断根)
|
||
var _enemy_rows_get: Callable # () -> Array——enemy 行集活读
|
||
var _difficulty_get: Callable # () -> DifficultyTable(可空——表缺省合法态)
|
||
var _warn_dedup: Dictionary[String, bool] = {} # R1 四元组去重注册表(自 ConfigDb 迁入)
|
||
|
||
|
||
func _init(diag_cb: Callable, board_gen_rows_cb: Callable,
|
||
enemy_rows_cb: Callable, difficulty_cb: Callable) -> void:
|
||
_diag = diag_cb
|
||
_board_gen_rows_get = board_gen_rows_cb
|
||
_enemy_rows_get = enemy_rows_cb
|
||
_difficulty_get = difficulty_cb
|
||
|
||
|
||
# 去重注册表清空(门面 load_tables / reset_diagnostics 调用——与拆分前清空时点逐位一致)
|
||
func reset_warn_dedup() -> void:
|
||
_warn_dedup.clear()
|
||
|
||
|
||
# ---- R1 难度行解析(2026-09-18 用户拍板修订:ceil 向上取整保证偏难;域越界与内容缺口 Fatal 退出)----
|
||
|
||
func resolve_board_gen(L: int, D: int) -> Dictionary:
|
||
return _resolve_progress(_board_gen_rows_get.call(), L, D, "board_gen")
|
||
|
||
|
||
func resolve_enemy_rowset(L: int, D: int) -> Array[Dictionary]:
|
||
# 行集数组形态(2026-10-07 敌人表行集多行批——原单行 Dictionary 退役):ceil 命中 (l*,d*) 后
|
||
# 返回该坐标全部行、按表文件行序(行序即契约——同坐标多行文件内相邻由 EnemyTable.validate 兜底)。
|
||
# 空集表达 = 空数组(生产表下 ceil 命中坐标恒有行,空集仅表空时可达——validate 已拦)。
|
||
return _resolve_progress(_enemy_rows_get.call(), L, D, "enemy", true)
|
||
|
||
|
||
# 难度曲线与Boss DifficultyTable 消费面(敌人系统.spawn 调用):(L,D) 精确匹配修饰乘数,越域值 clamp(GDD Edge Case——组合事故非配置事故)
|
||
func resolve_difficulty_modifiers(L: int, D: int) -> Dictionary:
|
||
var dt = _difficulty_get.call()
|
||
if dt == null:
|
||
return {}
|
||
for row in dt.rows:
|
||
if int(row.get("level_index", 0)) == L and int(row.get("node_depth", -1)) == D:
|
||
return {
|
||
"hp_mult": clampf(float(row.get("hp_mult", 1.0)), 0.1, 10.0),
|
||
"atk_mult": clampf(float(row.get("atk_mult", 1.0)), 0.1, 10.0),
|
||
}
|
||
return {}
|
||
|
||
|
||
func _resolve_progress(rows: Array, L: int, D: int, table_id: String, return_all := false) -> Variant:
|
||
if L < 1 or D < 0:
|
||
_diag.call("fatal", "request_oob", "%s 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [table_id, L, D])
|
||
return {}
|
||
var level_keys: Array[int] = []
|
||
for row in rows:
|
||
var lv := int(row.get("level_index", 0))
|
||
if not level_keys.has(lv):
|
||
level_keys.append(lv)
|
||
if level_keys.is_empty():
|
||
_diag.call("fatal", "structural", "%s 行集为空——锚行校验应已拦截" % table_id)
|
||
return {}
|
||
level_keys.sort()
|
||
var l_star := _ceil_key(level_keys, L)
|
||
var l_clamped := l_star < 0
|
||
if l_clamped:
|
||
l_star = int(level_keys[-1]) # 超出最大行 → 取最大行封顶(2026-09-18 追加拍板:可取范围内向上取整,超出用最大值)
|
||
var depth_keys: Array[int] = []
|
||
for row in rows:
|
||
if int(row.get("level_index", 0)) == l_star:
|
||
var dv := int(row.get("node_depth", 0))
|
||
if not depth_keys.has(dv):
|
||
depth_keys.append(dv)
|
||
depth_keys.sort()
|
||
var d_star := _ceil_key(depth_keys, D)
|
||
var d_clamped := d_star < 0
|
||
if d_clamped:
|
||
d_star = int(depth_keys[-1])
|
||
var missing := ""
|
||
if l_clamped and d_clamped:
|
||
missing = "both_clamp"
|
||
elif l_clamped:
|
||
missing = "level_clamp"
|
||
elif d_clamped:
|
||
missing = "depth_clamp"
|
||
elif l_star != L and d_star != D:
|
||
missing = "both_ceil"
|
||
elif l_star != L:
|
||
missing = "level_ceil"
|
||
elif d_star != D:
|
||
missing = "depth_ceil"
|
||
if missing != "":
|
||
var dedup_key := "%s|%s|%d|%d" % [table_id, missing, l_star, d_star]
|
||
if not _warn_dedup.has(dedup_key):
|
||
_warn_dedup[dedup_key] = true
|
||
var verb := "clamp 解析(超出最大行取最大值)" if missing.contains("clamp") else "ceil 解析(向上取整保证偏难)"
|
||
_diag.call("warning", "resolve_" + missing, "%s 请求 (%d,%d) %s → (%d,%d) [%s]——2026-09-18 拍板" % [table_id, L, D, verb, l_star, d_star, missing])
|
||
if return_all:
|
||
var all_out: Array[Dictionary] = []
|
||
for row in rows:
|
||
if int(row.get("level_index", 0)) == l_star and int(row.get("node_depth", 0)) == d_star:
|
||
all_out.append(row)
|
||
return all_out
|
||
for row in rows:
|
||
if int(row.get("level_index", 0)) == l_star and int(row.get("node_depth", 0)) == d_star:
|
||
return row
|
||
return {}
|
||
|
||
|
||
# 取 sorted_keys 中第一个 >= request 的键;无(请求高于最大行)返回 -1 → 调用方 Fatal
|
||
func _ceil_key(sorted_keys: Array, request: int) -> int:
|
||
for k in sorted_keys:
|
||
if int(k) >= request:
|
||
return int(k)
|
||
return -1
|