feat(state): 迁移 settings 切片(2 字段 / 2 臂)
This commit is contained in:
1 parent
9b3e76d42d
commit
6947fcb567
9 files changed
+165
-23
No files matched your search
@@ -143,7 +143,7 @@
|
||||
`names/root_wiring.json` + `TankiOffline/.../App/State/RootState.kt`、`RootWiring.kt`。
|
||||
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
|
||||
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
|
||||
- 已迁移切片 **13/89**:
|
||||
- 已迁移切片 **14/89**:
|
||||
- `inviteState` → `aD` / `pD.er5`(`InviteReducer.kt`)
|
||||
- `loginByPassword` → `gD` / `MD.cr6`(`LoginReducer.kt`,含 `SetLogin`/`SetPassword` 把 status 打回 `NONE` 的原语义)
|
||||
- `twitchState` → `g9` / `y9.gta`(`TwitchReducer.kt`;`SetAccount` 是 Twitch 账号,不是 UID)
|
||||
@@ -194,12 +194,15 @@
|
||||
`AddCoins`/`AddRubies` 把 `spent` 收回主余额后清零,`SpendCoins`/`SpendRubies` 同步累加 `spent`。
|
||||
`UpdateRank` 用 `min(rankNames.size, rank)` 重算 `normalizedRank`;`SetUserId(null)` 归零。
|
||||
3 个匿名动作按效果定名:`R8`→`DisableLobbyTutorial`、`v8`→`SetInDebt`、`p8`→`ClearInDebt`。
|
||||
- `settings` → `Uut` / `xw.ltg`(`SettingsReducer.kt`):2 个字段,2 个 `instanceof` 臂。
|
||||
`currentCategory` 是设置页分类枚举(`ACCOUNT`…`SUPPORT`,默认 `GAME`),
|
||||
`disableAccountSettings` 默认 false;`Fut`→`SetSettingsCategory`、`Gut`→`DisableAccountSettings`。
|
||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 12 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **76 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 13/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **318 项全绿**,含 89 槽位完整性、12 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 13 个有 reducer 的切片,
|
||||
`launchParams` 与其余 **75 个字段原样透传**;
|
||||
迁移进度用 `RootReducer.Coverage`(`已迁移 14/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **325 项全绿**,含 89 槽位完整性、13 个归约切片一次归约互不串片、未迁移字段透传,
|
||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
@@ -209,7 +212,7 @@
|
||||
效果是把 `HomeScreen.shopDiscountNotification` 置 true,对应主菜单商店项的折扣提示);
|
||||
shop 的 17 个匿名类按 reducer 效果定名并登记(`Yut`→`ShopLoaded`、`F5`→`ResetShop` 等);
|
||||
screen 的 9 个、lootBoxes 的 6 个、garage 的 25 个、garagePreview 的 15 个、
|
||||
entrance 的 6 个、user 的 3 个匿名类同样按效果定名并登记。
|
||||
entrance 的 6 个、user 的 3 个、settings 的 2 个匿名类同样按效果定名并登记。
|
||||
|
||||
### S4 引擎核心
|
||||
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generatedAt": "2026-10-23T08:14:22.248Z",
|
||||
"generatedAt": "2026-10-23T09:11:41.133Z",
|
||||
"module": "module_10032.js",
|
||||
"RootState": {
|
||||
"Class": "z6",
|
||||
@@ -19,6 +19,7 @@
|
||||
"garagePreview",
|
||||
"entrance",
|
||||
"user",
|
||||
"settings",
|
||||
"launchParams"
|
||||
],
|
||||
"AnonymousActions": [
|
||||
@@ -514,6 +515,18 @@
|
||||
"Name": "ClearInDebt",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "inDebt = false(`n.qtb(cd × 30, !1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "Fut",
|
||||
"Name": "SetSettingsCategory",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "currentCategory = action.category(`n.bu8(t.cu8_1)`)"
|
||||
},
|
||||
{
|
||||
"Local": "Gut",
|
||||
"Name": "DisableAccountSettings",
|
||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||
"Effect": "disableAccountSettings = true(`n.bu8(cd, !0)`)"
|
||||
}
|
||||
],
|
||||
"Markers": [
|
||||
@@ -1105,11 +1118,11 @@
|
||||
"Reducer": "xw.ltg",
|
||||
"Delegate": "xw.ltg(t, n.upv_1)",
|
||||
"Actions": [
|
||||
"?Fut",
|
||||
"?Gut"
|
||||
"DisableAccountSettings",
|
||||
"SetSettingsCategory"
|
||||
],
|
||||
"Default": "new Uut()",
|
||||
"Migrated": false
|
||||
"Migrated": true
|
||||
},
|
||||
{
|
||||
"Field": "accountSettings",
|
||||
|
||||
@@ -132,6 +132,10 @@ const AnonymousActionNames = new Map([
|
||||
['R8', 'DisableLobbyTutorial'],
|
||||
['v8', 'SetInDebt'],
|
||||
['p8', 'ClearInDebt'],
|
||||
// settings 切片(Uut / xw.ltg):2 个没有 toString / 不在 action_inventory 的类。
|
||||
// 括号里是原 reducer 的效果;实现见 SettingsReducer.kt。
|
||||
['Fut', 'SetSettingsCategory'],
|
||||
['Gut', 'DisableAccountSettings'],
|
||||
]);
|
||||
|
||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||
@@ -504,6 +508,7 @@ const Migrated = {
|
||||
garagePreview: { Type: 'GaragePreviewStateSlice', Reduce: 'ReduceGaragePreview' },
|
||||
entrance: { Type: 'EntranceStateSlice', Reduce: 'ReduceEntrance' },
|
||||
user: { Type: 'UserStateSlice', Reduce: 'ReduceUser' },
|
||||
settings: { Type: 'SettingsStateSlice', Reduce: 'ReduceSettings' },
|
||||
// 原根 reducer 对这一片没有调用,只有默认值 `ag()`(空 Map);这里仅做类型收口。
|
||||
launchParams: {
|
||||
Type: 'LaunchParamsStateSlice',
|
||||
@@ -640,6 +645,12 @@ const UserAnonymousEffects = {
|
||||
p8: 'inDebt = false(`n.qtb(cd × 30, !1)`)',
|
||||
};
|
||||
|
||||
// settings 切片(Uut / xw.ltg):没有 toString / 不在 action_inventory 的类,按 reducer 分支效果定名。
|
||||
const SettingsAnonymousEffects = {
|
||||
Fut: 'currentCategory = action.category(`n.bu8(t.cu8_1)`)',
|
||||
Gut: 'disableAccountSettings = true(`n.bu8(cd, !0)`)',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(P, 'names', 'root_wiring.json'),
|
||||
JSON.stringify(
|
||||
@@ -698,6 +709,12 @@ fs.writeFileSync(
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
...Object.entries(SettingsAnonymousEffects).map(([Local, Effect]) => ({
|
||||
Local,
|
||||
Name: AnonymousActionNames.get(Local),
|
||||
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
|
||||
Effect,
|
||||
})),
|
||||
],
|
||||
Markers: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// SettingsReducer.kt —— 设置切片(对应 module_10032 的 Uut 状态 + Hut.ltg reducer)
|
||||
//
|
||||
// 证据链:
|
||||
// 状态类 Uut:`function Uut(t, n)`,2 个字段,toString 名为
|
||||
// `Settings(currentCategory=…, disableAccountSettings=…)`。
|
||||
// 默认值:`currentCategory = i7()`(枚举 GAME=3),`disableAccountSettings = false`。
|
||||
// copy:`Uut.bu8(t, n, i)`,`cd` 表示保留原字段。
|
||||
// 根委派:`xw.ltg(t, n.upv_1)`。
|
||||
// reducer(`Hut.ltg`)只有两个分支:
|
||||
// `t instanceof Fut ? n.bu8(t.cu8_1) : t instanceof Gut ? n.bu8(cd, !0) : n`
|
||||
// `Fut` / `Gut` 没有 toString、也不在 action_inventory,按 reducer 效果定名:
|
||||
// Fut → SetSettingsCategory(只写 currentCategory)
|
||||
// Gut → DisableAccountSettings(只把 disableAccountSettings 置 true)
|
||||
package App.State.Reducers
|
||||
|
||||
import App.State.SettingsCategory
|
||||
|
||||
/* ------------------------------------------------------------------ 匿名动作 */
|
||||
|
||||
class SetSettingsCategory(val category: SettingsCategory)
|
||||
|
||||
class DisableAccountSettings
|
||||
|
||||
/* ------------------------------------------------------------------ 状态 */
|
||||
|
||||
data class SettingsStateSlice(
|
||||
val CurrentCategory: SettingsCategory = SettingsCategory.GAME,
|
||||
val DisableAccountSettings: Boolean = false,
|
||||
)
|
||||
|
||||
/* ------------------------------------------------------------------ reducer */
|
||||
|
||||
fun ReduceSettings(State0: SettingsStateSlice, Action: Any): SettingsStateSlice = when (Action) {
|
||||
is SetSettingsCategory -> State0.copy(CurrentCategory = Action.category)
|
||||
is DisableAccountSettings -> State0.copy(DisableAccountSettings = true)
|
||||
else -> State0
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||
//
|
||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||
// 这里采用同一形状。已迁移的 13 个切片里,12 个真正调用 reducer,launchParams 只做类型收口:
|
||||
// 这里采用同一形状。已迁移的 14 个切片里,13 个真正调用 reducer,launchParams 只做类型收口:
|
||||
//
|
||||
// inviteState → ReduceInvite(aD / pD.er5)
|
||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||
@@ -15,9 +15,10 @@
|
||||
// garagePreview → ReduceGaragePreview(IG / fs.eru,根委派 `fs.eru(t, n.epv_1)`)
|
||||
// entrance → ReduceEntrance(hD / Bv.pth,根委派 `Bv.pth(t, n.jpx_1)`)
|
||||
// user → ReduceUser(t8 / M8().qtd,根委派 `M8().qtd(t, n.ypu_1)`)
|
||||
// settings → ReduceSettings(Uut / xw.ltg,根委派 `xw.ltg(t, n.upv_1)`)
|
||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||
//
|
||||
// 其余 76 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 其余 75 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||
package App.State
|
||||
@@ -31,6 +32,7 @@ import App.State.Reducers.ReduceLocalBattleUser
|
||||
import App.State.Reducers.ReduceLoginByPassword
|
||||
import App.State.Reducers.ReduceLootBoxes
|
||||
import App.State.Reducers.ReduceScreen
|
||||
import App.State.Reducers.ReduceSettings
|
||||
import App.State.Reducers.ReduceShop
|
||||
import App.State.Reducers.ReduceTwitch
|
||||
import App.State.Reducers.ReduceUser
|
||||
@@ -60,6 +62,7 @@ object RootReducer {
|
||||
GaragePreview = ReduceGaragePreview(State0.GaragePreview, Action),
|
||||
Entrance = ReduceEntrance(State0.Entrance, Action),
|
||||
User = ReduceUser(State0.User, Action),
|
||||
Settings = ReduceSettings(State0.Settings, Action),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import App.State.Reducers.LocalBattleUserStateSlice
|
||||
import App.State.Reducers.LoginByPasswordStateSlice
|
||||
import App.State.Reducers.LootBoxesStateSlice
|
||||
import App.State.Reducers.ScreenStateSlice
|
||||
import App.State.Reducers.SettingsStateSlice
|
||||
import App.State.Reducers.ShopStateSlice
|
||||
import App.State.Reducers.TwitchStateSlice
|
||||
import App.State.Reducers.UserStateSlice
|
||||
@@ -66,8 +67,8 @@ data class RootState(
|
||||
val TipsState: Any? = null,
|
||||
/** 原 news(ZX / E_.asd)。未迁移:原样透传。 */
|
||||
val News: Any? = null,
|
||||
/** 原 settings(Uut / xw.ltg)。未迁移:原样透传。 */
|
||||
val Settings: Any? = null,
|
||||
/** 原 settings(Uut / xw.ltg)。已迁移。 */
|
||||
val Settings: SettingsStateSlice = SettingsStateSlice(),
|
||||
/** 原 accountSettings(oet / Lp.mtg)。未迁移:原样透传。 */
|
||||
val AccountSettings: Any? = null,
|
||||
/** 原 lootBoxes(aH / ws.wrv)。已迁移。 */
|
||||
|
||||
@@ -36,7 +36,7 @@ object RootWiring {
|
||||
SliceWiring("clansStorage", "rpv_1", "lO", "me.vr1", "me.vr1(t, n.rpv_1)", listOf("?mO", "AddUser", "AddUsersToNewAccepted", "BuyAdditionalPlace", "ClanLoaded", "ClanUnloaded", "ForeignClanLoaded", "MinimalRankChanged", "RecruitmentChanged", "RemoveUser", "RemoveUsersFromNewAccepted", "ShowForeignClan", "UpdateClan")),
|
||||
SliceWiring("tipsState", "spv_1", "dst", "Hw.vth", "Hw.vth(t, n.spv_1)", listOf("UpdateTips")),
|
||||
SliceWiring("news", "tpv_1", "ZX", "E_.asd", "E_.asd(t, n.tpv_1)", listOf("?hJ", "AddNewsItemAction", "RemoveNewsItemAction", "SetNewsItemAction", "SetUnreadNewsCounter")),
|
||||
SliceWiring("settings", "upv_1", "Uut", "xw.ltg", "xw.ltg(t, n.upv_1)", listOf("?Fut", "?Gut")),
|
||||
SliceWiring("settings", "upv_1", "Uut", "xw.ltg", "xw.ltg(t, n.upv_1)", listOf("DisableAccountSettings", "SetSettingsCategory")),
|
||||
SliceWiring("accountSettings", "vpv_1", "oet", "Lp.mtg", "Lp.mtg(t, n.vpv_1)", listOf("?aet", "?cet", "?det", "?fet", "?get", "?ket", "?met", "?pet", "?vet", "?wet", "?xet", "ClearInputUid", "SetAccountRemovalDays")),
|
||||
SliceWiring("lootBoxes", "wpv_1", "aH", "ws.wrv", "ws.wrv(t, n.wpv_1)", listOf("AddKeys", "ClearRewards", "LootBoxOpeningFailed", "SelectCategory", "SetContainerData", "SetCurrentContainer", "SetGoToGarage", "SetIsAccelerated", "SetIsBlockOpenButtons", "SetIsOpening", "SetIsReopening", "SetIsShopVisited", "SetKeys", "SetPeriodOfGiveLootBox", "SetPossibleRewards", "SetRewards", "SetTimeToGiveLootBox", "ShownRewards")),
|
||||
SliceWiring("notifications", "xpv_1", "?", "B_.ise", "B_.ise(t, n.xpv_1)", listOf("?PJ", "?RJ", "AddNotification", "InitNotificationSound")),
|
||||
@@ -106,7 +106,7 @@ object RootWiring {
|
||||
)
|
||||
|
||||
/** 已迁移(强类型;launchParams 为透传,不调用 reducer)的字段。 */
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "launchParams")
|
||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "launchParams")
|
||||
|
||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// SettingsModels.kt —— settings 切片用到的枚举(App.State 包内,供动作字段类型引用)
|
||||
//
|
||||
// 证据链:module_10032 的 `J2()` 初始化
|
||||
// `ACCOUNT=0, GRAPHIC=1, SOUND=2, GAME=3, CONTROL=4, HUD=5, SECURITY=6, BATTLE=7, SUPPORT=8`
|
||||
// `i7()` 返回 `mc`(GAME),即 `Uut` 的 currentCategory 默认值。
|
||||
package App.State
|
||||
|
||||
/** 原 `Z2`:设置页分类,顺序与枚举 ordinal 一致。 */
|
||||
enum class SettingsCategory {
|
||||
ACCOUNT,
|
||||
GRAPHIC,
|
||||
SOUND,
|
||||
GAME,
|
||||
CONTROL,
|
||||
HUD,
|
||||
SECURITY,
|
||||
BATTLE,
|
||||
SUPPORT,
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
// ⑥ 动作目录:816 个类与 138 个真实派发名对齐
|
||||
// ⑦ 回放:真实 toString 样例的类/字段/类型校验
|
||||
// ⑧ 全目录动作类都能按 KClass 路由
|
||||
// ⑨~㉓ 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// Shop(含 U7 类别表与 w3 物品表两个子 reducer)/ Screen / LootBoxes / Garage / GaragePreview / Entrance / User;
|
||||
// ⑨~㉔ 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
|
||||
// Shop(含 U7 类别表与 w3 物品表两个子 reducer)/ Screen / LootBoxes / Garage / GaragePreview / Entrance / User / Settings;
|
||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||
//
|
||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||
@@ -100,6 +100,7 @@ import App.State.SetRankNames
|
||||
import App.State.SetRubies
|
||||
import App.State.SetUserPropertiesAction
|
||||
import App.State.SetUserId
|
||||
import App.State.SettingsCategory
|
||||
import App.State.SpendCoins
|
||||
import App.State.SpendCrystals
|
||||
import App.State.SpendRubies
|
||||
@@ -263,9 +264,13 @@ import App.State.Reducers.ClearGaragePreviewParams
|
||||
import App.State.Reducers.ClearGrenadeData
|
||||
import App.State.Reducers.ClearHasGrenades
|
||||
import App.State.Reducers.ClearInDebt
|
||||
import App.State.Reducers.DisableAccountSettings
|
||||
import App.State.Reducers.DisableLobbyTutorial
|
||||
import App.State.Reducers.ReduceSettings
|
||||
import App.State.Reducers.ReduceUser
|
||||
import App.State.Reducers.SetInDebt
|
||||
import App.State.Reducers.SetSettingsCategory
|
||||
import App.State.Reducers.SettingsStateSlice
|
||||
import App.State.Reducers.UserRankBounds
|
||||
import App.State.Reducers.UserStateSlice
|
||||
import App.State.Reducers.ClearHullData
|
||||
@@ -693,7 +698,7 @@ object StateCheck {
|
||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||
}
|
||||
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 13 个已迁移切片(12 归约 + launchParams 透传)
|
||||
// ⑭ 根 reducer:89 个槽位的委派表 + 14 个已迁移切片(13 归约 + launchParams 透传)
|
||||
run {
|
||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||
Check(
|
||||
@@ -757,14 +762,14 @@ object StateCheck {
|
||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||
)
|
||||
Check(
|
||||
"根:迁移表 = 13 个已迁移字段,其余 76 个待迁",
|
||||
"根:迁移表 = 14 个已迁移字段,其余 75 个待迁",
|
||||
RootReducer.Migrated ==
|
||||
setOf(
|
||||
"inviteState", "loginByPassword", "twitchState", "home",
|
||||
"localBattleUserState", "shop", "screen", "lootBoxes", "garage",
|
||||
"garagePreview", "entrance", "user", "launchParams",
|
||||
"garagePreview", "entrance", "user", "settings", "launchParams",
|
||||
) &&
|
||||
RootWiring.Unmigrated.size == 76
|
||||
RootWiring.Unmigrated.size == 75
|
||||
)
|
||||
|
||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||
@@ -820,7 +825,7 @@ object StateCheck {
|
||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||
)
|
||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 13/89")
|
||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 14/89")
|
||||
|
||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||
@@ -2643,6 +2648,50 @@ object StateCheck {
|
||||
)
|
||||
}
|
||||
|
||||
// ㉔ 切片 reducer:Settings(原 module_10032 的 Uut / xw.ltg,2 字段;2 个 instanceof 臂)
|
||||
run {
|
||||
val S0 = SettingsStateSlice()
|
||||
Check(
|
||||
"切片 Settings:默认 GAME / disableAccountSettings=false",
|
||||
S0.CurrentCategory == SettingsCategory.GAME && !S0.DisableAccountSettings
|
||||
)
|
||||
Check(
|
||||
"切片 Settings:SetSettingsCategory 只写 currentCategory",
|
||||
ReduceSettings(S0, SetSettingsCategory(SettingsCategory.ACCOUNT)).let {
|
||||
it.CurrentCategory == SettingsCategory.ACCOUNT && !it.DisableAccountSettings
|
||||
}
|
||||
)
|
||||
Check(
|
||||
"切片 Settings:DisableAccountSettings 只把开关置 true",
|
||||
ReduceSettings(
|
||||
S0.copy(CurrentCategory = SettingsCategory.SOUND),
|
||||
DisableAccountSettings(),
|
||||
).let {
|
||||
it.CurrentCategory == SettingsCategory.SOUND && it.DisableAccountSettings
|
||||
}
|
||||
)
|
||||
Check("切片 Settings:无关动作不改状态", ReduceSettings(S0, AddFrags(1)) == S0)
|
||||
|
||||
val Root0 = RootState()
|
||||
val Root1 = ReduceRoot(Root0, SetSettingsCategory(SettingsCategory.CONTROL))
|
||||
Check(
|
||||
"根:SetSettingsCategory 只动 settings",
|
||||
Root1.Settings.CurrentCategory == SettingsCategory.CONTROL &&
|
||||
Root1.User == Root0.User && Root1.Home == Root0.Home
|
||||
)
|
||||
Check(
|
||||
"根:settings 无关动作保留前一次归约",
|
||||
ReduceRoot(Root1, AddFrags(1)).Settings == Root1.Settings
|
||||
)
|
||||
|
||||
val W = RootWiring.ByField("settings")!!
|
||||
Check(
|
||||
"根:settings 委派到 Uut / xw.ltg 且 2 个动作全部具名",
|
||||
W.SliceClass == "Uut" && W.Reducer == "xw.ltg" &&
|
||||
W.Actions.toSet() == setOf("DisableAccountSettings", "SetSettingsCategory")
|
||||
)
|
||||
}
|
||||
|
||||
val Failed = Results.filter { !it.second }
|
||||
println("TankiOffline 状态层自检:${Results.size} 项")
|
||||
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)
|
||||
|
||||
Reference in new issue
Block a user