feat(state): 迁移 entrance 切片(8 字段 / 7 臂)

This commit is contained in:
TermiNexus committed 2026-10-23 15:47:18 +08:00
1 parent 435cd3191e
commit 77a90fdfff
8 files changed
+255 -29

No files matched your search

+12 -6
View File
@@ -143,7 +143,7 @@
`names/root_wiring.json` + `TankiOffline/.../App/State/RootState.kt`、`RootWiring.kt`。
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
- 已迁移切片 **11/89**:
- 已迁移切片 **12/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)
@@ -181,12 +181,17 @@
`TankPartData` / `TankPreviewSettings` / `HullEngineType` / `TurretMechanism` 见 `GaragePreviewModels.kt`;
12 个匿名动作按效果定名(`BG`→`CaptureScreenshot` … `tH`→`ClearDroneData`),
3 个单例臂定名 `ClearGaragePreviewParams` / `ShowGaragePreview` / `HideGaragePreview`,不在 `Actions` 表里。
- `entrance` → `hD` / `Bv.pth`(`EntranceReducer.kt`):8 个布尔字段,7 个 `instanceof` 臂。
`showSocialNetworks` 缺省 true,其余 false;`HideSocialNetworks` 置 false,
`SetControlsForChina` / `SetRunningInChinaDataCenter` / `SetRunningInChinaPartners` /
`SetAuthorizedByChinaSdkToken` / `SetClassic` 各置一个 true,`SetAgeWarnShow` 写入 `isAgeWarnShow`。
原 reducer 用 `ur4` 的 `cd` 参数保留其余字段;`authorizedByClassicEarlyAccessToken` 没有写入臂。
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 10 个有 reducer 的切片,
`launchParams` 与其余 **78 个字段原样透传**;
迁移进度用 `RootReducer.Coverage`(`已迁移 11/89`)与 `RootWiring.Unmigrated` 暴露。
- 自检:`TankiOffline/tools/RunStateTest.ps1` **280 项全绿**,含 89 槽位完整性、10 个归约切片一次归约互不串片、未迁移字段透传,
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 11 个有 reducer 的切片,
`launchParams` 与其余 **77 个字段原样透传**;
迁移进度用 `RootReducer.Coverage`(`已迁移 12/89`)与 `RootWiring.Unmigrated` 暴露。
- 自检:`TankiOffline/tools/RunStateTest.ps1` **294 项全绿**,含 89 槽位完整性、11 个归约切片一次归约互不串片、未迁移字段透传,
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
@@ -195,7 +200,8 @@
`o1` → `ShowShopDiscountNotification`(`$_$.gl` 单例,由 module_18334 的 `Qx.qge` 派发;
效果是把 `HomeScreen.shopDiscountNotification` 置 true,对应主菜单商店项的折扣提示);
shop 的 17 个匿名类按 reducer 效果定名并登记(`Yut`→`ShopLoaded`、`F5`→`ResetShop` 等);
screen 的 9 个、lootBoxes 的 6 个、garage 的 25 个、garagePreview 的 15 个匿名类同样按效果定名并登记。
screen 的 9 个、lootBoxes 的 6 个、garage 的 25 个、garagePreview 的 15 个、
entrance 的 6 个匿名类同样按效果定名并登记。
### S4 引擎核心
- 模块:32088(3D 数学)、92980(渲染)、61378(ECS)、55088(物理)、36659 + 71105(资源)、36734(音频)、3569(输入)
+46 -9
View File
@@ -1,5 +1,5 @@
{
"generatedAt": "2026-10-23T07:24:48.002Z",
"generatedAt": "2026-10-23T07:37:58.358Z",
"module": "module_10032.js",
"RootState": {
"Class": "z6",
@@ -17,6 +17,7 @@
"lootBoxes",
"garage",
"garagePreview",
"entrance",
"launchParams"
],
"AnonymousActions": [
@@ -458,6 +459,42 @@
"Name": "HideGaragePreview",
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
"Effect": "isVisible = false(`n.trs(!1)`)"
},
{
"Local": "eit",
"Name": "HideSocialNetworks",
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
"Effect": "showSocialNetworks = false(`n.ur4(!1)`)"
},
{
"Local": "uit",
"Name": "SetControlsForChina",
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
"Effect": "controlsForChina = true(`n.ur4(cd, !0)`)"
},
{
"Local": "sit",
"Name": "SetRunningInChinaDataCenter",
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
"Effect": "isRunningInChinaDataCenter = true(`n.ur4(cd, cd, !0)`)"
},
{
"Local": "oit",
"Name": "SetRunningInChinaPartners",
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
"Effect": "isRunningInChinaPartners = true(`n.ur4(cd, cd, cd, !0)`)"
},
{
"Local": "lit",
"Name": "SetAuthorizedByChinaSdkToken",
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
"Effect": "authorizedByChinaSdkToken = true(`n.ur4(cd, cd, cd, cd, cd, !0)`)"
},
{
"Local": "fit",
"Name": "SetClassic",
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
"Effect": "isClassic = true(`n.ur4(cd, cd, cd, cd, cd, cd, !0)`)"
}
],
"Markers": [
@@ -1813,16 +1850,16 @@
"Reducer": "Bv.pth",
"Delegate": "Bv.pth(t, n.jpx_1)",
"Actions": [
"?eit",
"?fit",
"?lit",
"?oit",
"?sit",
"?uit",
"SetAgeWarnShow"
"HideSocialNetworks",
"SetAgeWarnShow",
"SetAuthorizedByChinaSdkToken",
"SetClassic",
"SetControlsForChina",
"SetRunningInChinaDataCenter",
"SetRunningInChinaPartners"
],
"Default": "new hD()",
"Migrated": false
"Migrated": true
},
{
"Field": "antiAddiction",
+25
View File
@@ -119,6 +119,14 @@ const AnonymousActionNames = new Map([
['is', 'ClearGaragePreviewParams'],
['es', 'ShowGaragePreview'],
['rs', 'HideGaragePreview'],
// entrance 切片(hD / Bv.pth):6 个没有 toString / 不在 action_inventory 的类。
// 括号里是原 reducer 的效果;实现见 EntranceReducer.kt。
['eit', 'HideSocialNetworks'],
['uit', 'SetControlsForChina'],
['sit', 'SetRunningInChinaDataCenter'],
['oit', 'SetRunningInChinaPartners'],
['lit', 'SetAuthorizedByChinaSdkToken'],
['fit', 'SetClassic'],
]);
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
@@ -489,6 +497,7 @@ const Migrated = {
lootBoxes: { Type: 'LootBoxesStateSlice', Reduce: 'ReduceLootBoxes' },
garage: { Type: 'GarageStateSlice', Reduce: 'ReduceGarage' },
garagePreview: { Type: 'GaragePreviewStateSlice', Reduce: 'ReduceGaragePreview' },
entrance: { Type: 'EntranceStateSlice', Reduce: 'ReduceEntrance' },
// 原根 reducer 对这一片没有调用,只有默认值 `ag()`(空 Map);这里仅做类型收口。
launchParams: {
Type: 'LaunchParamsStateSlice',
@@ -608,6 +617,16 @@ const GaragePreviewAnonymousEffects = {
rs: 'isVisible = false(`n.trs(!1)`)',
};
// entrance 切片(hD / Bv.pth):没有 toString / 不在 action_inventory 的类,按 reducer 分支效果定名。
const EntranceAnonymousEffects = {
eit: 'showSocialNetworks = false(`n.ur4(!1)`)',
uit: 'controlsForChina = true(`n.ur4(cd, !0)`)',
sit: 'isRunningInChinaDataCenter = true(`n.ur4(cd, cd, !0)`)',
oit: 'isRunningInChinaPartners = true(`n.ur4(cd, cd, cd, !0)`)',
lit: 'authorizedByChinaSdkToken = true(`n.ur4(cd, cd, cd, cd, cd, !0)`)',
fit: 'isClassic = true(`n.ur4(cd, cd, cd, cd, cd, cd, !0)`)',
};
fs.writeFileSync(
path.join(P, 'names', 'root_wiring.json'),
JSON.stringify(
@@ -654,6 +673,12 @@ fs.writeFileSync(
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
Effect,
})),
...Object.entries(EntranceAnonymousEffects).map(([Local, Effect]) => ({
Local,
Name: AnonymousActionNames.get(Local),
DispatchedAt: '未在 action_trace_merged.json 中出现;按 reducer 分支效果定名',
Effect,
})),
],
Markers: [
{
@@ -0,0 +1,58 @@
// EntranceReducer.kt —— 启动入口切片(对应 module_10032 的 hD 状态 + Bv.pth reducer)
//
// 证据链:
// 状态类 hD:`function hD(t, n, i, r, e, u, s, o)`,8 个布尔字段,
// toString 名为 `EntranceState(showSocialNetworks=…, …, authorizedByClassicEarlyAccessToken=…)`。
// 默认值:showSocialNetworks = true(`t = t === cd || t`),其余 7 个都是 false
// (`x = x !== cd && x`)。
//
// 根委派:`Bv.pth(t, n.jpx_1)`。pth 有 7 个 instanceof 臂 + 默认透传:
// eit → showSocialNetworks = false
// uit → controlsForChina = true
// sit → isRunningInChinaDataCenter = true
// oit → isRunningInChinaPartners = true
// _it → isAgeWarnShow = action.isShow(SetAgeWarnShow)
// lit → authorizedByChinaSdkToken = true
// fit → isClassic = true
// 所有臂都走 `ur4`:参数为 `cd` 时保留原值,所以每次只改一个字段。
// `authorizedByClassicEarlyAccessToken` 在原 reducer 里没有写入臂,保持默认 false。
//
// 6 个匿名动作没有 toString / 不在 action_inventory,按 reducer 效果定名;
// `_it` 在 action_inventory 里已有名字,直接复用生成的 SetAgeWarnShow。
package App.State.Reducers
import App.State.SetAgeWarnShow
/* ------------------------------------------------------------------ 匿名动作 */
class HideSocialNetworks
class SetControlsForChina
class SetRunningInChinaDataCenter
class SetRunningInChinaPartners
class SetAuthorizedByChinaSdkToken
class SetClassic
/* ------------------------------------------------------------------ 状态 */
data class EntranceStateSlice(
val ShowSocialNetworks: Boolean = true,
val ControlsForChina: Boolean = false,
val IsRunningInChinaDataCenter: Boolean = false,
val IsRunningInChinaPartners: Boolean = false,
val IsAgeWarnShow: Boolean = false,
val AuthorizedByChinaSdkToken: Boolean = false,
val IsClassic: Boolean = false,
val AuthorizedByClassicEarlyAccessToken: Boolean = false,
)
/* ------------------------------------------------------------------ reducer */
fun ReduceEntrance(State0: EntranceStateSlice, Action: Any): EntranceStateSlice = when (Action) {
is HideSocialNetworks -> State0.copy(ShowSocialNetworks = false)
is SetControlsForChina -> State0.copy(ControlsForChina = true)
is SetRunningInChinaDataCenter -> State0.copy(IsRunningInChinaDataCenter = true)
is SetRunningInChinaPartners -> State0.copy(IsRunningInChinaPartners = true)
is SetAgeWarnShow -> State0.copy(IsAgeWarnShow = Action.isShow)
is SetAuthorizedByChinaSdkToken -> State0.copy(AuthorizedByChinaSdkToken = true)
is SetClassic -> State0.copy(IsClassic = true)
else -> State0
}
@@ -1,7 +1,7 @@
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
//
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
// 这里采用同一形状。已迁移的 11 个切片里,10 个真正调用 reducer,launchParams 只做类型收口:
// 这里采用同一形状。已迁移的 12 个切片里,11 个真正调用 reducer,launchParams 只做类型收口:
//
// inviteState → ReduceInvite(aD / pD.er5)
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
@@ -13,13 +13,15 @@
// lootBoxes → ReduceLootBoxes(aH / EH.wrv)
// garage → ReduceGarage(UB / hF,根委派 `i = hF(t, n)`)
// garagePreview → ReduceGaragePreview(IG / fs.eru,根委派 `fs.eru(t, n.epv_1)`)
// entrance → ReduceEntrance(hD / Bv.pth,根委派 `Bv.pth(t, n.jpx_1)`)
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
//
// 其余 78 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
// 其余 77 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
package App.State
import App.State.Reducers.ReduceEntrance
import App.State.Reducers.ReduceGarage
import App.State.Reducers.ReduceGaragePreview
import App.State.Reducers.ReduceHome
@@ -54,6 +56,7 @@ object RootReducer {
LootBoxes = ReduceLootBoxes(State0.LootBoxes, Action),
Garage = ReduceGarage(State0.Garage, Action),
GaragePreview = ReduceGaragePreview(State0.GaragePreview, Action),
Entrance = ReduceEntrance(State0.Entrance, Action),
)
}
@@ -4,6 +4,7 @@
// 已迁移的切片用强类型;其余保持 Any?(原样透传),迁移一个改一个再重新生成。
package App.State
import App.State.Reducers.EntranceStateSlice
import App.State.Reducers.GarageStateSlice
import App.State.Reducers.GaragePreviewStateSlice
import App.State.Reducers.HomeStateSlice
@@ -146,8 +147,8 @@ data class RootState(
val LaunchParams: LaunchParamsStateSlice = emptyMap(),
/** 原 partner(UJ / (inline@partner))。未迁移:原样透传。 */
val Partner: Any? = null,
/** 原 entrance(hD / Bv.pth)。未迁移:原样透传。 */
val Entrance: Any? = null,
/** 原 entrance(hD / Bv.pth)。已迁移。 */
val Entrance: EntranceStateSlice = EntranceStateSlice(),
/** 原 antiAddiction(UC / W.iq8)。未迁移:原样透传。 */
val AntiAddiction: Any? = null,
/** 原 spectator(HA / Li.jqm)。未迁移:原样透传。 */
@@ -77,7 +77,7 @@ object RootWiring {
SliceWiring("language", "gpx_1", "?", "m6().jtg", "m6().jtg(t, n.gpx_1)", listOf("?d6")),
SliceWiring("launchParams", "hpx_1", "?", "(pass-through)", "n.hpx_1", listOf()),
SliceWiring("partner", "ipx_1", "UJ", "(inline@partner)", "(function (t, n) { var i; if (t instanceof VJ) i = n.osf(t.rsf_1, cd, cd, cd, cd, cd, cd, cd, cd, cd, t.ssf_1); else if (t instanceof nZ) { var r = t.bsg_1, e = t.csg_1, u = t.dsg_1, s = t.esg_1, o = t.fsg_1, _ = t.gsg_1; i = n.osf(cd, cd, cd, r, e, u, cd, cd, o, _, s); } else i = t instanceof iZ ? n.osf(cd, t.hsg_1) : t instanceof uZ ? n.osf(cd, cd, t.ksg_1) : t instanceof eZ ? n.osf(cd, cd, cd, cd, cd, cd, cd, t.jsg_1) : t instanceof _Z ? n.osf(cd, cd, cd, cd, cd, cd, t.osg_1) : t instanceof X …", listOf("?JJ", "?_Z", "?hZ", "?tZ", "InitPartnerInviteAction", "InitSocialNetworkParameters", "SetLoginParams", "SetLoginStatusForBinding", "SetPartnerId", "SetPartnerParameters", "SetPartnerReady")),
SliceWiring("entrance", "jpx_1", "hD", "Bv.pth", "Bv.pth(t, n.jpx_1)", listOf("?eit", "?fit", "?lit", "?oit", "?sit", "?uit", "SetAgeWarnShow")),
SliceWiring("entrance", "jpx_1", "hD", "Bv.pth", "Bv.pth(t, n.jpx_1)", listOf("HideSocialNetworks", "SetAgeWarnShow", "SetAuthorizedByChinaSdkToken", "SetClassic", "SetControlsForChina", "SetRunningInChinaDataCenter", "SetRunningInChinaPartners")),
SliceWiring("antiAddiction", "kpx_1", "UC", "W.iq8", "W.iq8(t, n.kpx_1)", listOf("?FC", "?XC", "?YC", "SetRealNameAndIdNumber", "SetValidateAntiAddictionUserDataStatus")),
SliceWiring("spectator", "lpx_1", "HA", "Li.jqm", "Li.jqm(t, n.lpx_1)", listOf("?JA", "?XA", "?YA", "?ZA", "SetSpectator", "UpdateHudLayout")),
SliceWiring("moderation", "mpx_1", "NI", "Ei.oqh", "Ei.oqh(t, n.mpx_1)", listOf("?FI", "?GI", "?JI", "?KI", "?QI", "?UI", "?WI", "?XI", "?YI", "?ZI", "?nA", "?tA", "?uA")),
@@ -106,7 +106,7 @@ object RootWiring {
)
/** 已迁移(强类型;launchParams 为透传,不调用 reducer)的字段。 */
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "launchParams")
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "launchParams")
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
@@ -9,8 +9,8 @@
// ⑥ 动作目录:816 个类与 138 个真实派发名对齐
// ⑦ 回放:真实 toString 样例的类/字段/类型校验
// ⑧ 全目录动作类都能按 KClass 路由
// ⑨~㉑ 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
// Shop(含 U7 类别表与 w3 物品表两个子 reducer)/ Screen / LootBoxes / Garage / GaragePreview;
// ⑨~㉒ 切片 reducer:InviteState / LoginByPasswordState / TwitchState / HomeScreen / LocalBattleUserState /
// Shop(含 U7 类别表与 w3 物品表两个子 reducer)/ Screen / LootBoxes / Garage / GaragePreview / Entrance;
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
//
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
@@ -217,6 +217,7 @@ import App.State.GaragePreviewModelCC
import App.State.HullEngineType
import App.State.InitGarageResources
import App.State.ResetItem3dModelActionCache
import App.State.SetAgeWarnShow
import App.State.SetCaptureActions
import App.State.SetDrone
import App.State.SetExpectedItemId
@@ -255,8 +256,16 @@ import App.State.Reducers.PreviewHullCategory
import App.State.Reducers.PreviewPaintCategory
import App.State.Reducers.PreviewWeaponCategory
import App.State.Reducers.ReduceGarage
import App.State.Reducers.EntranceStateSlice
import App.State.Reducers.HideSocialNetworks
import App.State.Reducers.ReduceEntrance
import App.State.Reducers.ReduceGaragePreview
import App.State.Reducers.RemoveNewItem
import App.State.Reducers.SetAuthorizedByChinaSdkToken
import App.State.Reducers.SetClassic
import App.State.Reducers.SetControlsForChina
import App.State.Reducers.SetRunningInChinaDataCenter
import App.State.Reducers.SetRunningInChinaPartners
import App.State.Reducers.RemoveWaitServerItemMount
import App.State.Reducers.ResetGarage
import App.State.Reducers.ResetMountDelay
@@ -653,7 +662,7 @@ object StateCheck {
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
}
// ⑭ 根 reducer:89 个槽位的委派表 + 11 个已迁移切片(10 归约 + launchParams 透传)
// ⑭ 根 reducer:89 个槽位的委派表 + 12 个已迁移切片(11 归约 + launchParams 透传)
run {
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
Check(
@@ -717,17 +726,17 @@ object StateCheck {
LocalBattleW.Reducer == "(inline@localBattleUserState)"
)
Check(
"根:迁移表 = 11 个已迁移字段,其余 78 个待迁",
"根:迁移表 = 12 个已迁移字段,其余 77 个待迁",
RootReducer.Migrated ==
setOf(
"inviteState", "loginByPassword", "twitchState", "home",
"localBattleUserState", "shop", "screen", "lootBoxes", "garage",
"garagePreview", "launchParams",
"garagePreview", "entrance", "launchParams",
) &&
RootWiring.Unmigrated.size == 78
RootWiring.Unmigrated.size == 77
)
// 一次 ReduceRoot 里八个切片各归约自己的动作,互不串片
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
val S0 = RootState(User = "user-1", Screen = ScreenStateSlice(Current = NamedScreen("Preloader")))
val S1 = ReduceRoot(S0, ApplyInvite("uid-1"))
Check(
@@ -780,7 +789,7 @@ object StateCheck {
S5.User == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
)
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 11/89")
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 12/89")
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
Store.Dispatch(SetStatus("LOGGING_IN"))
@@ -2329,6 +2338,93 @@ object StateCheck {
)
}
// ㉒ 切片 reducer:Entrance(原 module_10032 的 hD / Bv.pth,8 字段;7 个 instanceof 臂)
run {
val S0 = EntranceStateSlice()
Check(
"切片 Entrance:默认值与原构造一致(showSocialNetworks 缺省 true,其余 false)",
S0.ShowSocialNetworks && !S0.ControlsForChina &&
!S0.IsRunningInChinaDataCenter && !S0.IsRunningInChinaPartners &&
!S0.IsAgeWarnShow && !S0.AuthorizedByChinaSdkToken &&
!S0.IsClassic && !S0.AuthorizedByClassicEarlyAccessToken
)
Check(
"切片 Entrance:HideSocialNetworks 置 showSocialNetworks=false",
!ReduceEntrance(S0, HideSocialNetworks()).ShowSocialNetworks
)
Check(
"切片 Entrance:SetControlsForChina 置 controlsForChina=true",
ReduceEntrance(S0, SetControlsForChina()).ControlsForChina
)
Check(
"切片 Entrance:SetRunningInChinaDataCenter 置对应字段",
ReduceEntrance(S0, SetRunningInChinaDataCenter()).IsRunningInChinaDataCenter
)
Check(
"切片 Entrance:SetRunningInChinaPartners 置对应字段",
ReduceEntrance(S0, SetRunningInChinaPartners()).IsRunningInChinaPartners
)
Check(
"切片 Entrance:SetAgeWarnShow 写入 isAgeWarnShow",
ReduceEntrance(S0, SetAgeWarnShow(true)).IsAgeWarnShow &&
!ReduceEntrance(S0.copy(IsAgeWarnShow = true), SetAgeWarnShow(false)).IsAgeWarnShow
)
Check(
"切片 Entrance:SetAuthorizedByChinaSdkToken 置对应字段",
ReduceEntrance(S0, SetAuthorizedByChinaSdkToken()).AuthorizedByChinaSdkToken
)
Check(
"切片 Entrance:SetClassic 置 isClassic",
ReduceEntrance(S0, SetClassic()).IsClassic
)
val All = listOf(
HideSocialNetworks(),
SetControlsForChina(),
SetRunningInChinaDataCenter(),
SetRunningInChinaPartners(),
SetAgeWarnShow(true),
SetAuthorizedByChinaSdkToken(),
SetClassic(),
).fold(S0) { S, A -> ReduceEntrance(S, A) }
Check(
"切片 Entrance:七个动作依次归约后只改对应字段",
!All.ShowSocialNetworks && All.ControlsForChina &&
All.IsRunningInChinaDataCenter && All.IsRunningInChinaPartners &&
All.IsAgeWarnShow && All.AuthorizedByChinaSdkToken &&
All.IsClassic && !All.AuthorizedByClassicEarlyAccessToken
)
Check("切片 Entrance:无关动作不改状态", ReduceEntrance(All, AddFrags(1)) == All)
val Root0 = RootState()
val Root1 = ReduceRoot(Root0, SetClassic())
Check(
"根:SetClassic 只动 entrance",
Root1.Entrance.IsClassic && Root1.LoginByPassword == Root0.LoginByPassword &&
Root1.GaragePreview == Root0.GaragePreview && Root1.Garage == Root0.Garage
)
Check(
"根:entrance 无关动作保留前一次归约",
ReduceRoot(Root1, AddFrags(1)).Entrance == Root1.Entrance
)
val W = RootWiring.ByField("entrance")!!
Check(
"根:entrance 委派到 hD / Bv.pth 且 7 个动作全部具名",
W.SliceClass == "hD" && W.Reducer == "Bv.pth" && W.Actions.size == 7 &&
W.Actions.none { it.startsWith("?") }
)
Check(
"根:entrance 的动作名覆盖 7 个 instanceof 臂",
listOf(
"HideSocialNetworks", "SetAgeWarnShow", "SetAuthorizedByChinaSdkToken",
"SetClassic", "SetControlsForChina", "SetRunningInChinaDataCenter",
"SetRunningInChinaPartners",
).all { it in W.Actions }
)
}
val Failed = Results.filter { !it.second }
println("TankiOffline 状态层自检:${Results.size} 项")
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)