iter56-卡1:结算期文字列表退役与日志零文案(迭代56卡1): 撤B区逐行文字列表(row_pacer文字入带三调用/行格式化域删净——FX排播链零diff保留)+日志step行零文案(text/display_name不落盘)+reward_ineffective六发射点补reason结构化(full_layers/full_hp/no_enemy_alive/hero_down); 分析工具改读结构化字段(target==all_enemies/reason优先text兜底双分支)+analyze_parity_check对拍载体。读数: R1零逐行文字/R2 FX链行型分布独立推导逐位一致/R3零文案+全字段落盘/R4判读等价三读数全一致/R5四类reason逐一命中——各T提交信息载; 能力行:137/:138名实一致(_smoke_settle_zero_rows/_assert_fx_chain/_assert_no_text_and_full_payload/_assert_four_reasons); 测试削弱全部申报内(§10清单+§5.5同生死波及面11处登记实现报告); 中档审计通过
This commit is contained in:
1 parent
9251d35650
commit
908e518306
40 files changed
+1258
-1298
No files matched your search
@@ -15,11 +15,18 @@ var _problems: Array = []
|
||||
# 记参假站桩(d12 排播半):继承真类以过类型面,只记解析入参
|
||||
class FakeStage extends BattleStageView:
|
||||
var calls: Array[Array] = []
|
||||
var fx_rows: Array[Dictionary] = [] # on_step_row_fx 收到的行(FX 链计数载体)
|
||||
|
||||
func on_step_row_fx(row: Dictionary) -> void:
|
||||
fx_rows.append(row.duplicate(true))
|
||||
|
||||
func enemy_standee_center(target_id: String, display_name: String) -> Variant:
|
||||
calls.append([target_id, display_name])
|
||||
return Vector2(10, 10)
|
||||
|
||||
func hero_standee_center() -> Vector2:
|
||||
return Vector2(10, 10)
|
||||
|
||||
|
||||
# 记参假演出层(同上——play_* 全部只记不演)
|
||||
class FakeFx extends SettlementFxView:
|
||||
@@ -105,19 +112,12 @@ func _init() -> void:
|
||||
main.ui.screens.row_pacer.flush()
|
||||
var snap_after: String = JSON.stringify(battle.diagnostic_snapshot())
|
||||
check(snap_before == snap_after, "排空前后核心诊断快照逐位一致(AC⑤ 演出关停零分叉)")
|
||||
# ---- 断言②:零丢行(结构判据:排空后队列恒空 + 末信号行原文在带——append_row 直落不吞行)----
|
||||
# ---- 断言②:零丢行(逐行文字列表退役后改判〔退役改 V-退役卡 R2〕:结构判据=排空后队列恒空,
|
||||
# 行的落地面由「原文在明细带」改为「逐行进 FX 链」——由下方 _assert_fx_chain 对全行集断言承接)----
|
||||
check(rows_seen.size() > 0, "结算行已产生(断言前提)")
|
||||
check(main.ui.screens.row_pacer.pending_rows().is_empty(), "排空后队列恒空(flush 完整性)")
|
||||
var last_text := ""
|
||||
for i in range(rows_seen.size() - 1, -1, -1):
|
||||
var cand_row: Dictionary = rows_seen[i]
|
||||
last_text = String(cand_row.get("text", ""))
|
||||
if last_text == "":
|
||||
last_text = String(cand_row.get("display_name", ""))
|
||||
if last_text != "":
|
||||
break
|
||||
check(last_text != "" and main.ui.battle.log_view.parsed_text().contains(last_text),
|
||||
"末信号行原文在明细带(排空不吞行:『%s』)" % last_text)
|
||||
# ---- 断言②改判承接:FX 链逐行收拍(真实行集驱动——每行一拍站桩反馈,弹道/标出按型计数逐位对上)----
|
||||
_assert_fx_chain(main, rows_seen)
|
||||
# ---- 断言③:段间延迟取数面双态 ----
|
||||
UiKit.motion_scale = 1.0
|
||||
var d_on: float = main.pace_delay_for("damage", "heal")
|
||||
@@ -156,6 +156,110 @@ func _count_row(row: Dictionary, arr: Array) -> void:
|
||||
arr.append(row.duplicate(true))
|
||||
|
||||
|
||||
# FX 排播链断言(逐行文字列表退役后的行落地面——〔退役改 V-退役卡 R2〕):
|
||||
# 判据出处: design/ux/battle.md:439 动效:结算逐行兑现为信息载体不可整体跳过,可加倍(减动效只调时长)
|
||||
# 判据出处: design/gdd/08-Alpha版本标准.md:154 战斗演出链(弹道 / 受击 / 血条 / 灰化)在役
|
||||
# 真实行集(夹具采样的 step_row 载荷)驱动独立 RowPacer,断言:
|
||||
# ① 每行恰好一拍站桩反馈(on_step_row_fx 计数=行数);② 弹道/标出调用计数与行型分布逐位对上
|
||||
# (期望从行集独立推导、实际从记参假件读——不镜像实现);③ 断言前提=行集非空(非空自检)。
|
||||
# 记参假棋盘 FX(highlight 分支载体——perfect sweep / seal hit 弹道只记不演)
|
||||
class FakeBoardFx extends BoardFxView:
|
||||
var calls: Array[String] = []
|
||||
|
||||
func play_perfect_sweep() -> void:
|
||||
calls.append("perfect_sweep")
|
||||
|
||||
func play_seal_hit_projectile(_heavy: bool) -> void:
|
||||
calls.append("seal_hit_projectile")
|
||||
|
||||
|
||||
# 记参假 toast(skill_unlock 行载体)
|
||||
class FakeToast extends ToastStack:
|
||||
var texts: Array[String] = []
|
||||
|
||||
func show_toast(text: String, _tone: String = "info") -> void:
|
||||
texts.append(text)
|
||||
|
||||
|
||||
# 记参假棋盘区(_consume_row highlight 分支的 fx/toast 载体)
|
||||
class FakeBoardZone extends BoardZoneView:
|
||||
var board_fx := FakeBoardFx.new()
|
||||
var toast_stack := FakeToast.new()
|
||||
|
||||
|
||||
func _assert_fx_chain(main: Node, rows_seen: Array) -> void:
|
||||
var rp = RowPacerScript.new()
|
||||
var fstage := FakeStage.new(null, root.get_node("/root/ConfigDB").presentation.battle_layout)
|
||||
var ffx := FakeFx.new()
|
||||
var fzone := FakeBoardZone.new(root.get_node("/root/ConfigDB").presentation.battle_layout)
|
||||
fzone.fx = fzone.board_fx
|
||||
fzone.toast = fzone.toast_stack
|
||||
rp.stage = fstage
|
||||
rp.board_view = main.ui.battle.board_zone.board_view
|
||||
rp.settlement_fx = ffx
|
||||
rp.board_zone = fzone
|
||||
rp.refresh_request = func() -> void: pass
|
||||
rp.pump_ended = func() -> void: pass
|
||||
for row in rows_seen:
|
||||
rp.enqueue(row.duplicate(true))
|
||||
rp.flush()
|
||||
check(rows_seen.size() > 0, "FX 链断言前提:行集非空(非空自检)")
|
||||
check(fstage.fx_rows.size() == rows_seen.size(),
|
||||
"每行恰好一拍站桩反馈(on_step_row_fx %d/%d)〔退役改 V-退役卡 R2〕" % [fstage.fx_rows.size(), rows_seen.size()])
|
||||
# 期望计数从行集独立推导(演出语义=0.4 硬契约:伤害行弹道+数字、治疗行弹道+数字、效果行色环)
|
||||
var exp_projectile := 0
|
||||
var exp_mark := 0
|
||||
var exp_pulse := 0
|
||||
for row in rows_seen:
|
||||
var t := String(row.get("type", ""))
|
||||
var tgt := String(row.get("target", ""))
|
||||
if t == "damage":
|
||||
exp_projectile += 1
|
||||
exp_mark += 1
|
||||
elif t == "heal" and (tgt == "hero" or tgt == ""):
|
||||
exp_projectile += 1
|
||||
exp_mark += 1
|
||||
elif t == "heal":
|
||||
exp_mark += 1
|
||||
elif t == "effect":
|
||||
exp_pulse += 1
|
||||
var got_projectile := 0
|
||||
var got_mark := 0
|
||||
var got_pulse := 0
|
||||
for c in ffx.calls:
|
||||
match String(c[0]):
|
||||
"projectile": got_projectile += 1
|
||||
"mark": got_mark += 1
|
||||
"pulse": got_pulse += 1
|
||||
check(got_projectile == exp_projectile,
|
||||
"跨区弹道计数与行型分布逐位一致(%d/%d)〔退役改 V-退役卡 R2〕" % [got_projectile, exp_projectile])
|
||||
check(got_mark == exp_mark,
|
||||
"结算标出数字计数与行型分布逐位一致(%d/%d)〔退役改 V-退役卡 R2〕" % [got_mark, exp_mark])
|
||||
check(got_pulse == exp_pulse,
|
||||
"状态色环计数与行型分布逐位一致(%d/%d)〔退役改 V-退役卡 R2〕" % [got_pulse, exp_pulse])
|
||||
# highlight 三路(完美封印横幅=高光行非解锁技;封印命中加重弹道=seal_hit 高亮键不限行型;
|
||||
# Boss 解锁技名 toast=skill_unlock 键)——期望按行协议语义独立推导
|
||||
var exp_sweep := 0
|
||||
var exp_seal_hit := 0
|
||||
var exp_toast := 0
|
||||
for row in rows_seen:
|
||||
var t := String(row.get("type", ""))
|
||||
var hl := String(row.get("highlight", ""))
|
||||
if t == "highlight" and hl != "skill_unlock":
|
||||
exp_sweep += 1
|
||||
elif hl == "seal_hit":
|
||||
exp_seal_hit += 1
|
||||
if hl == "skill_unlock":
|
||||
exp_toast += 1
|
||||
check(fzone.board_fx.calls.count("perfect_sweep") == exp_sweep,
|
||||
"完美封印横幅计数与行分布逐位一致(%d/%d)〔退役改 V-退役卡 R2〕" % [fzone.board_fx.calls.count("perfect_sweep"), exp_sweep])
|
||||
check(fzone.board_fx.calls.count("seal_hit_projectile") == exp_seal_hit,
|
||||
"封印命中弹道计数与行分布逐位一致(%d/%d)〔退役改 V-退役卡 R2〕" % [fzone.board_fx.calls.count("seal_hit_projectile"), exp_seal_hit])
|
||||
check(fzone.toast_stack.texts.size() == exp_toast,
|
||||
"解锁技名 toast 计数与行分布逐位一致(%d/%d)〔退役改 V-退役卡 R2〕" % [fzone.toast_stack.texts.size(), exp_toast])
|
||||
rp.free()
|
||||
|
||||
|
||||
func _finish() -> void:
|
||||
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
|
||||
for p in ["user://test_pacing_queue_save.json", "user://test_pacing_queue_save.json.tmp"]:
|
||||
|
||||
Reference in new issue
Block a user