Files
36Wisdom/biz/service/level_play_test.go
T
adminandClaude Opus 4.7 414c7de007 feat: 分支闯关判分与终局结算(含单测)
choose 校验节点/选项归属与解锁链,终局在 common.WithLock 内按
技术设计 4.3/4.4 结算:首次到达才结算、连续失败限扣、余额不为负、
完美集齐全终局 +20 并解锁计策卡与下一计;路径流水尽力而为。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-13 12:47:01 +08:00

136 lines
4.6 KiB
Go
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.
package service
import (
"testing"
"36wisdom/biz/consts"
)
func state() SettleState {
return SettleState{ReachedFinals: map[int64]bool{}, TotalFinals: 5, BalanceAfter: 100}
}
func TestSettleFinal_BestFirstTime(t *testing.T) {
f := SettleFinal(state(), 101, consts.ResultBest)
if f.ScoreDelta != consts.PointsBest {
t.Fatalf("首次最佳应 +%d,实际 %d", consts.PointsBest, f.ScoreDelta)
}
if !f.Cleared {
t.Fatal("到达最佳终局应通关")
}
if f.Stars != 3 {
t.Fatalf("最佳应 3 星,实际 %d", f.Stars)
}
if f.Perfect {
t.Fatal("仅一个终局不应完美")
}
if f.BalanceAfter != 130 {
t.Fatalf("余额应 130,实际 %d", f.BalanceAfter)
}
}
func TestSettleFinal_GoodFirstTime(t *testing.T) {
f := SettleFinal(state(), 101, consts.ResultGood)
if f.ScoreDelta != consts.PointsGood {
t.Fatalf("首次良好应 +%d,实际 %d", consts.PointsGood, f.ScoreDelta)
}
if f.Cleared {
t.Fatal("良好终局不应通关")
}
if f.Stars != 2 {
t.Fatalf("良好应 2 星,实际 %d", f.Stars)
}
}
func TestSettleFinal_FailFirstTime(t *testing.T) {
f := SettleFinal(state(), 101, consts.ResultFail)
if f.ScoreDelta != consts.PointsFail {
t.Fatalf("首次失败应 %d,实际 %d", consts.PointsFail, f.ScoreDelta)
}
if f.Stars != 0 {
t.Fatalf("失败应 0 星,实际 %d", f.Stars)
}
}
func TestSettleFinal_FailStreakLimit(t *testing.T) {
// 连续失败 2 次后不再扣分:第 3 次到达失败终局 delta=0
s := SettleState{FailStreak: 2, ReachedFinals: map[int64]bool{1: true, 2: true}, TotalFinals: 5, BalanceAfter: 100}
f := SettleFinal(s, 3, consts.ResultFail)
if f.ScoreDelta != 0 {
t.Fatalf("连续失败第 3 次应不再扣分,实际 %d", f.ScoreDelta)
}
// 连续失败第 2 次仍扣
s2 := SettleState{FailStreak: 1, ReachedFinals: map[int64]bool{1: true}, TotalFinals: 5, BalanceAfter: 100}
f2 := SettleFinal(s2, 2, consts.ResultFail)
if f2.ScoreDelta != consts.PointsFail {
t.Fatalf("连续失败第 2 次应扣 %d,实际 %d", consts.PointsFail, f2.ScoreDelta)
}
}
func TestSettleFinal_BalanceFloor(t *testing.T) {
s := SettleState{ReachedFinals: map[int64]bool{}, TotalFinals: 5, BalanceAfter: 5}
f := SettleFinal(s, 1, consts.ResultFail)
if f.ScoreDelta != -5 {
t.Fatalf("余额不足应扣到 0-5),实际 %d", f.ScoreDelta)
}
if f.BalanceAfter != 0 {
t.Fatalf("余额应 0,实际 %d", f.BalanceAfter)
}
}
func TestSettleFinal_ClearedNoSettle(t *testing.T) {
// 已通关后补分支:只记完成度不结算积分
s := SettleState{LevelCleared: true, ReachedFinals: map[int64]bool{101: true}, TotalFinals: 5, BalanceAfter: 130}
f := SettleFinal(s, 102, consts.ResultGood)
if f.ScoreDelta != 0 {
t.Fatalf("已通关补分支应不结算,实际 %d", f.ScoreDelta)
}
}
func TestSettleFinal_Perfect(t *testing.T) {
s := SettleState{ReachedFinals: map[int64]bool{1: true, 2: true, 3: true, 4: true}, TotalFinals: 5, BalanceAfter: 100}
f := SettleFinal(s, 5, consts.ResultGood)
if !f.Perfect {
t.Fatal("全部终局到达应完美")
}
if f.ScoreDelta != consts.PointsGood+consts.PointsPerfect {
t.Fatalf("应 +%d(良好+完美),实际 %d", consts.PointsGood+consts.PointsPerfect, f.ScoreDelta)
}
}
func TestSettleFinal_PerfectOnlyOnce(t *testing.T) {
// 已完美(进度表标记)后重复到达:不再触发完美奖励
s := SettleState{LevelCleared: true, PerfectAwarded: true, ReachedFinals: map[int64]bool{1: true, 2: true, 3: true, 4: true, 5: true}, TotalFinals: 5, BalanceAfter: 100}
f := SettleFinal(s, 5, consts.ResultBest)
if f.Perfect {
t.Fatal("已完美不应重复触发")
}
if f.ScoreDelta != 0 {
t.Fatalf("重复到达应不结算,实际 %d", f.ScoreDelta)
}
}
func TestSettleFinal_PerfectWithLogDrift(t *testing.T) {
// 日志已集齐但进度未发放(日志尽力而为可能漂移):本次到达应补发完美奖励
s := SettleState{LevelCleared: true, ReachedFinals: map[int64]bool{1: true, 2: true, 3: true, 4: true, 5: true}, TotalFinals: 5, BalanceAfter: 100}
f := SettleFinal(s, 5, consts.ResultGood)
if !f.Perfect {
t.Fatal("日志集齐但未发放时应补发完美")
}
if f.ScoreDelta != consts.PointsPerfect {
t.Fatalf("应仅 +%d 完美奖励,实际 %d", consts.PointsPerfect, f.ScoreDelta)
}
}
func TestSettleFinal_RepeatFinal(t *testing.T) {
// 重复路线不重复结算
s := SettleState{ReachedFinals: map[int64]bool{101: true}, TotalFinals: 5, BalanceAfter: 100}
f := SettleFinal(s, 101, consts.ResultBest)
if f.ScoreDelta != 0 {
t.Fatalf("重复终局应不结算,实际 %d", f.ScoreDelta)
}
if !f.Cleared {
t.Fatal("重复到达最佳仍应标记通关")
}
}