feat(state): 迁移 battlesSelect(复用 BattleParams/BattleInfoUser)
This commit is contained in:
1 parent
71aa9a5256
commit
cd597b4693
8 files changed
+434
-23
No files matched your search
@@ -143,7 +143,7 @@
|
|||||||
`names/root_wiring.json` + `TankiOffline/.../App/State/RootState.kt`、`RootWiring.kt`。
|
`names/root_wiring.json` + `TankiOffline/.../App/State/RootState.kt`、`RootWiring.kt`。
|
||||||
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
|
- 根状态 `z6`(`TOState`)的 **89 个槽位**全部入表;字段顺序取 `toString`,槽位取构造函数 `<名>_1`。
|
||||||
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
|
- 根 reducer `k6` 的逐切片委派记全:reducer 引用、委派表达式、顶层 `instanceof` 动作名。
|
||||||
- 已迁移切片 **80/89**:
|
- 已迁移切片 **81/89**:
|
||||||
- `inviteState` → `aD` / `pD.er5`(`InviteReducer.kt`)
|
- `inviteState` → `aD` / `pD.er5`(`InviteReducer.kt`)
|
||||||
- `loginByPassword` → `gD` / `MD.cr6`(`LoginReducer.kt`,含 `SetLogin`/`SetPassword` 把 status 打回 `NONE` 的原语义)
|
- `loginByPassword` → `gD` / `MD.cr6`(`LoginReducer.kt`,含 `SetLogin`/`SetPassword` 把 status 打回 `NONE` 的原语义)
|
||||||
- `twitchState` → `g9` / `y9.gta`(`TwitchReducer.kt`;`SetAccount` 是 Twitch 账号,不是 UID)
|
- `twitchState` → `g9` / `y9.gta`(`TwitchReducer.kt`;`SetAccount` 是 Twitch 账号,不是 UID)
|
||||||
@@ -403,12 +403,18 @@
|
|||||||
`WasRegistered` 写等待时间与模式并清 `requestSent`;`EnterToBattleApply` 同时置两个进行中位;
|
`WasRegistered` 写等待时间与模式并清 `requestSent`;`EnterToBattleApply` 同时置两个进行中位;
|
||||||
`WH`→`ResetMatchmakingProgress`、`tW`/`nW`→`StartLoadingBattle`/`CancelLoadingBattle`;
|
`WH`→`ResetMatchmakingProgress`、`tW`/`nW`→`StartLoadingBattle`/`CancelLoadingBattle`;
|
||||||
模式表复用生成物 `MatchmakingModeRank`,`rankIndexToMinGS` 收口为 `Map<String, Int>`。
|
模式表复用生成物 `MatchmakingModeRank`,`rankIndexToMinGS` 收口为 `Map<String, Int>`。
|
||||||
|
- `battlesSelect` → `fA` / `Mi.vqk`(`BattlesSelectReducer.kt`):15 字段,20 个实例臂。
|
||||||
|
`AddBattle` 把 `BattleCreateParameters`(+ suspicionLevel)转成 `BattleParams` 并建 users / score 空表;
|
||||||
|
`AddUsers` 批量写 users / usersTeam 并同步个人分与可疑标记(`AddUser` 复用它);
|
||||||
|
`SwapTeam` 换队并把该战斗内用户分数归零;`RemoveBattle` / `RemoveUser` 清对应的四张子表;
|
||||||
|
其余为名字 / 可疑度 / 队伍分 / 个人分 / 资金 / 奖励上限 / 观战标记。
|
||||||
|
模型全部复用生成物:`BattleParams` / `BattleInfoUser` / `BattleCreateParameters` / `ProBattleRewardLimitData`。
|
||||||
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
- `launchParams` → `(pass-through)`:原根 reducer 对 `hpx_1` 没有调用,缺省是 `ag()` 空 Map;
|
||||||
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
`RootState.LaunchParams` 收口为 `LaunchParamsStateSlice = Map<String, String>`,不新增 reducer/动作。
|
||||||
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 79 个有 reducer 的切片,
|
- `App/State/RootReducer.kt`:`ReduceRoot(State0, Action)` 归约上述 80 个有 reducer 的切片,
|
||||||
`launchParams` 与其余 **9 个字段原样透传**;
|
`launchParams` 与其余 **8 个字段原样透传**;
|
||||||
迁移进度用 `RootReducer.Coverage`(`已迁移 80/89`)与 `RootWiring.Unmigrated` 暴露。
|
迁移进度用 `RootReducer.Coverage`(`已迁移 81/89`)与 `RootWiring.Unmigrated` 暴露。
|
||||||
- 自检:`TankiOffline/tools/RunStateTest.ps1` **871 项全绿**,含 89 槽位完整性、79 个归约切片一次归约互不串片、未迁移字段透传,
|
- 自检:`TankiOffline/tools/RunStateTest.ps1` **888 项全绿**,含 89 槽位完整性、80 个归约切片一次归约互不串片、未迁移字段透传,
|
||||||
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
以及用 `action_trace_merged.json` 真实派发的两条商店动作(`SetCoinPaymentProviderUrl` / `ToggleShopActivity`)回放。
|
||||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"generatedAt": "2026-10-24T12:37:28.603Z",
|
"generatedAt": "2026-10-24T12:57:54.249Z",
|
||||||
"module": "module_10032.js",
|
"module": "module_10032.js",
|
||||||
"RootState": {
|
"RootState": {
|
||||||
"Class": "z6",
|
"Class": "z6",
|
||||||
@@ -86,7 +86,8 @@
|
|||||||
"maps",
|
"maps",
|
||||||
"battleChat",
|
"battleChat",
|
||||||
"remoteUserDataStorage",
|
"remoteUserDataStorage",
|
||||||
"matchmaking"
|
"matchmaking",
|
||||||
|
"battlesSelect"
|
||||||
],
|
],
|
||||||
"AnonymousActions": [
|
"AnonymousActions": [
|
||||||
{
|
{
|
||||||
@@ -1432,6 +1433,18 @@
|
|||||||
"Name": "CancelLoadingBattle",
|
"Name": "CancelLoadingBattle",
|
||||||
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||||
"Effect": "startLoadingBattle=false(`n.brw(cd, cd, cd, cd, !1)`)"
|
"Effect": "startLoadingBattle=false(`n.brw(cd, cd, cd, cd, !1)`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Local": "gA",
|
||||||
|
"Name": "MarkBattlesLoaded",
|
||||||
|
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||||
|
"Effect": "loaded=true(`n.hqj(!0)`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Local": "dA",
|
||||||
|
"Name": "ResetBattlesSelect",
|
||||||
|
"DispatchedAt": "未在 action_trace_merged.json 中出现;按 reducer 分支效果定名",
|
||||||
|
"Effect": "new fA() 整片复位"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Markers": [
|
"Markers": [
|
||||||
@@ -2156,8 +2169,6 @@
|
|||||||
"Reducer": "Mi.vqk",
|
"Reducer": "Mi.vqk",
|
||||||
"Delegate": "Mi.vqk(t, n.apw_1)",
|
"Delegate": "Mi.vqk(t, n.apw_1)",
|
||||||
"Actions": [
|
"Actions": [
|
||||||
"?dA",
|
|
||||||
"?gA",
|
|
||||||
"AddBattle",
|
"AddBattle",
|
||||||
"AddUser",
|
"AddUser",
|
||||||
"AddUsers",
|
"AddUsers",
|
||||||
@@ -2165,8 +2176,10 @@
|
|||||||
"EnterToBattleInfo",
|
"EnterToBattleInfo",
|
||||||
"InitProBattleRewardLimit",
|
"InitProBattleRewardLimit",
|
||||||
"LimitReached",
|
"LimitReached",
|
||||||
|
"MarkBattlesLoaded",
|
||||||
"RemoveBattle",
|
"RemoveBattle",
|
||||||
"RemoveUser",
|
"RemoveUser",
|
||||||
|
"ResetBattlesSelect",
|
||||||
"RoundFinish",
|
"RoundFinish",
|
||||||
"RoundStarted",
|
"RoundStarted",
|
||||||
"SetReEnterProtectBattleId",
|
"SetReEnterProtectBattleId",
|
||||||
@@ -2178,7 +2191,7 @@
|
|||||||
"UpdateUserSuspicion"
|
"UpdateUserSuspicion"
|
||||||
],
|
],
|
||||||
"Default": "new fA()",
|
"Default": "new fA()",
|
||||||
"Migrated": false
|
"Migrated": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Field": "maps",
|
"Field": "maps",
|
||||||
|
|||||||
@@ -327,6 +327,9 @@ const AnonymousActionNames = new Map([
|
|||||||
['WH', 'ResetMatchmakingProgress'],
|
['WH', 'ResetMatchmakingProgress'],
|
||||||
['tW', 'StartLoadingBattle'],
|
['tW', 'StartLoadingBattle'],
|
||||||
['nW', 'CancelLoadingBattle'],
|
['nW', 'CancelLoadingBattle'],
|
||||||
|
// battlesSelect 切片(fA / MA.vqk):gA/dA 没有 toString。
|
||||||
|
['gA', 'MarkBattlesLoaded'],
|
||||||
|
['dA', 'ResetBattlesSelect'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
// 非动作的 `instanceof`:屏幕标识类,用于 GoTo 分支判断(不是 dispatch 的动作)。
|
||||||
@@ -811,6 +814,7 @@ const Migrated = {
|
|||||||
Reduce: 'ReduceRemoteUserDataStorage',
|
Reduce: 'ReduceRemoteUserDataStorage',
|
||||||
},
|
},
|
||||||
matchmaking: { Type: 'MatchmakingStateSlice', Reduce: 'ReduceMatchmaking' },
|
matchmaking: { Type: 'MatchmakingStateSlice', Reduce: 'ReduceMatchmaking' },
|
||||||
|
battlesSelect: { Type: 'BattlesSelectStateSlice', Reduce: 'ReduceBattlesSelect' },
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
for (const R of Rows) R.Migrated = Object.prototype.hasOwnProperty.call(Migrated, R.Field);
|
||||||
@@ -1226,8 +1230,9 @@ const AppSettingsAnonymousEffects = {
|
|||||||
WH: 'matchmakingAndLoadingBattleInProgress=false、startLoadingBattle=false、requestSent=false',
|
WH: 'matchmakingAndLoadingBattleInProgress=false、startLoadingBattle=false、requestSent=false',
|
||||||
tW: 'startLoadingBattle=true(`n.brw(cd, cd, cd, cd, !0)`)',
|
tW: 'startLoadingBattle=true(`n.brw(cd, cd, cd, cd, !0)`)',
|
||||||
nW: 'startLoadingBattle=false(`n.brw(cd, cd, cd, cd, !1)`)',
|
nW: 'startLoadingBattle=false(`n.brw(cd, cd, cd, cd, !1)`)',
|
||||||
|
gA: 'loaded=true(`n.hqj(!0)`)',
|
||||||
|
dA: 'new fA() 整片复位',
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(P, 'names', 'root_wiring.json'),
|
path.join(P, 'names', 'root_wiring.json'),
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
|
|||||||
@@ -0,0 +1,238 @@
|
|||||||
|
// BattlesSelectReducer.kt —— 战斗列表切片(对应 module_10032 的 fA 状态 + MA.vqk)
|
||||||
|
//
|
||||||
|
// 证据链:
|
||||||
|
// 状态类 fA:15 个字段,toString 名 "BattlesSelect(…)";copy 是 hqj(15 字段 + 回调)。
|
||||||
|
// 根委派:`Mi.vqk(t, n.apw_1)`。
|
||||||
|
// reducer(20 个实例臂):
|
||||||
|
// TA(RoundStarted) → roundEndTimes[battleId] = 当前时间 + 剩余秒;score[battleId] 清空
|
||||||
|
// IA(SwapTeam) → 该战斗内所有用户交换队伍,并把他们的个人分数归零
|
||||||
|
// AA(RoundFinish) → roundEndTimes / fund 删掉该战斗
|
||||||
|
// gA(无 toString) → loaded=true
|
||||||
|
// mA(AddBattle) → battles[battleId]=BattleParams;users / score 建空表;creators 写创建者
|
||||||
|
// kA(RemoveBattle) → battles / users / creators / alreadySeeBattleInfo 删该战斗
|
||||||
|
// zA(ChangeName) → battles[battleId].name
|
||||||
|
// bA(UpdateSuspicion) → battles[battleId].suspicionLevel
|
||||||
|
// yA(AddUsers) → 批量写 users / usersTeam(`$A` AddUser 复用它)
|
||||||
|
// xA(RemoveUser) → users / usersTeam / userScore / userSuspicion / userSuspicionByIp 删该用户
|
||||||
|
// jA(UpdateUserScore) → userScore[userId]
|
||||||
|
// CA(UpdateUserSuspicion)→ userSuspicion / userSuspicionByIp
|
||||||
|
// qA(UpdateTeamScore) → score[battleId][team]
|
||||||
|
// dA(无 toString) → `new fA()` 整片复位
|
||||||
|
// RA(EnterToBattleInfo) → alreadySeeBattleInfo += battleId
|
||||||
|
// SA(UpdateFund) → fund[battleId]
|
||||||
|
// EA(InitProBattleRewardLimit)→ proLimit
|
||||||
|
// PA(LimitReached) → isLimitReached
|
||||||
|
// NA(SetReEnterProtectBattleId)→ reEnterProtectBattleId
|
||||||
|
//
|
||||||
|
// 模型直接复用生成物:`BattleParams`(战斗描述)、`BattleInfoUser`(列表里的用户)、
|
||||||
|
// `BattleCreateParameters`(AddBattle 载荷)、`ProBattleRewardLimitData`。
|
||||||
|
package App.State.Reducers
|
||||||
|
|
||||||
|
import App.State.AddBattle
|
||||||
|
import App.State.AddUser
|
||||||
|
import App.State.AddUsers
|
||||||
|
import App.State.BattleCreateParameters
|
||||||
|
import App.State.BattleInfoUser
|
||||||
|
import App.State.BattleParams
|
||||||
|
import App.State.ChangeName
|
||||||
|
import App.State.EnterToBattleInfo
|
||||||
|
import App.State.InitProBattleRewardLimit
|
||||||
|
import App.State.LimitReached
|
||||||
|
import App.State.ProBattleRewardLimitData
|
||||||
|
import App.State.RemoveBattle
|
||||||
|
import App.State.RemoveUser
|
||||||
|
import App.State.RoundFinish
|
||||||
|
import App.State.RoundStarted
|
||||||
|
import App.State.SetReEnterProtectBattleId
|
||||||
|
import App.State.SwapTeam
|
||||||
|
import App.State.UpdateFund
|
||||||
|
import App.State.UpdateSuspicion
|
||||||
|
import App.State.UpdateTeamScore
|
||||||
|
import App.State.UpdateUserScore
|
||||||
|
import App.State.UpdateUserSuspicion
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ 匿名动作 */
|
||||||
|
|
||||||
|
/** 原 `gA`:战斗列表已加载。 */
|
||||||
|
object MarkBattlesLoaded
|
||||||
|
|
||||||
|
/** 原 `dA`:整片复位(`new fA()`)。 */
|
||||||
|
object ResetBattlesSelect
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ 状态 */
|
||||||
|
|
||||||
|
data class BattlesSelectStateSlice(
|
||||||
|
val Loaded: Boolean = false,
|
||||||
|
val Battles: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val Score: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val Users: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val Creators: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val UsersTeam: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val UserScore: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val UserSuspicion: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val UserSuspicionByIp: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val RoundEndTimes: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val AlreadySeeBattleInfo: Set<Any?> = emptySet(),
|
||||||
|
val Fund: Map<Any?, Any?> = emptyMap(),
|
||||||
|
val ProLimit: ProBattleRewardLimitData? = null,
|
||||||
|
val IsLimitReached: Boolean = false,
|
||||||
|
val ReEnterProtectBattleId: Any? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ reducer */
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private fun Inner(Map: Map<Any?, Any?>, Key: Any?): Map<Any?, Any?> =
|
||||||
|
Map[Key] as? Map<Any?, Any?> ?: emptyMap()
|
||||||
|
|
||||||
|
/** `BattleCreateParameters` → 列表用的 `BattleParams`(原 `new vA(...)`)。 */
|
||||||
|
private fun ParamsOf(
|
||||||
|
Params: BattleCreateParameters,
|
||||||
|
SuspicionLevel: Any?,
|
||||||
|
): BattleParams = BattleParams(
|
||||||
|
map = Params.mapId,
|
||||||
|
battleMode = 0,
|
||||||
|
format = Params.formatMode,
|
||||||
|
limits = Params.limits,
|
||||||
|
mapId = Params.mapId,
|
||||||
|
maxPeopleCount = Params.maxPeopleCount,
|
||||||
|
name = Params.name?.toString() ?: "",
|
||||||
|
parkourMode = Params.battleMode == "PARKOUR",
|
||||||
|
valuableBattle = Params.battleOptions.contains("VALUABLE"),
|
||||||
|
privateBattle = Params.battleOptions.contains("PRIVATE"),
|
||||||
|
proBattle = Params.proBattle,
|
||||||
|
rankRange = Params.rankRange,
|
||||||
|
theme = Params.theme.toIntOrNull() ?: 0,
|
||||||
|
suspicionLevel = SuspicionLevel,
|
||||||
|
options = Params.battleOptions,
|
||||||
|
)
|
||||||
|
|
||||||
|
/** 原 `eP`:队伍互换(字符串队伍名)。 */
|
||||||
|
private fun Swap(Team: Any?): Any? = when (Team) {
|
||||||
|
"RED", "red" -> "BLUE"
|
||||||
|
"BLUE", "blue" -> "RED"
|
||||||
|
else -> Team
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ReduceBattlesSelect(
|
||||||
|
State0: BattlesSelectStateSlice,
|
||||||
|
Action: Any,
|
||||||
|
): BattlesSelectStateSlice = when (Action) {
|
||||||
|
is RoundStarted -> State0.copy(
|
||||||
|
RoundEndTimes = State0.RoundEndTimes + (Action.battleId to Action.timeLeftInSec),
|
||||||
|
Score = State0.Score + (Action.battleId to emptyMap<Any?, Any?>()),
|
||||||
|
)
|
||||||
|
is SwapTeam -> {
|
||||||
|
val Teams = Inner(State0.UsersTeam, Action.battleId)
|
||||||
|
val Swapped = Teams.mapValues { (_, Team) -> Swap(Team) }
|
||||||
|
val Users = Inner(State0.Users, Action.battleId)
|
||||||
|
val Zeroed = State0.UserScore.mapValues { (UserId, _) ->
|
||||||
|
if (Users.containsKey(UserId)) 0 else State0.UserScore[UserId]
|
||||||
|
}
|
||||||
|
State0.copy(
|
||||||
|
UsersTeam = State0.UsersTeam + (Action.battleId to Swapped),
|
||||||
|
UserScore = Zeroed,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is RoundFinish -> State0.copy(
|
||||||
|
RoundEndTimes = State0.RoundEndTimes - Action.battleId,
|
||||||
|
Fund = State0.Fund - Action.battleId,
|
||||||
|
)
|
||||||
|
is MarkBattlesLoaded -> State0.copy(Loaded = true)
|
||||||
|
is AddBattle -> State0.copy(
|
||||||
|
Battles = State0.Battles + (
|
||||||
|
Action.battleId to ParamsOf(Action.params, Action.suspicionLevel)
|
||||||
|
),
|
||||||
|
Users = State0.Users + (Action.battleId to emptyMap<Any?, Any?>()),
|
||||||
|
Score = State0.Score + (Action.battleId to emptyMap<Any?, Any?>()),
|
||||||
|
Creators = State0.Creators + (Action.battleId to Action.creatorId),
|
||||||
|
)
|
||||||
|
is RemoveBattle -> State0.copy(
|
||||||
|
Battles = State0.Battles - Action.battleId,
|
||||||
|
Users = State0.Users - Action.battleId,
|
||||||
|
Creators = State0.Creators - Action.battleId,
|
||||||
|
AlreadySeeBattleInfo = State0.AlreadySeeBattleInfo - Action.battleId,
|
||||||
|
)
|
||||||
|
is ChangeName -> {
|
||||||
|
val Battle = State0.Battles[Action.battleId] as? BattleParams
|
||||||
|
if (Battle == null) State0
|
||||||
|
else State0.copy(
|
||||||
|
Battles = State0.Battles + (
|
||||||
|
Action.battleId to Battle.copy(name = Action.name?.toString() ?: Battle.name)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is UpdateSuspicion -> {
|
||||||
|
val Battle = State0.Battles[Action.battleId] as? BattleParams
|
||||||
|
if (Battle == null) State0
|
||||||
|
else State0.copy(
|
||||||
|
Battles = State0.Battles + (
|
||||||
|
Action.battleId to Battle.copy(suspicionLevel = Action.suspicionLevel)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is AddUsers -> {
|
||||||
|
var Users = State0.Users
|
||||||
|
var Teams = State0.UsersTeam
|
||||||
|
var Scores = State0.UserScore
|
||||||
|
var Suspicion = State0.UserSuspicion
|
||||||
|
var SuspicionByIp = State0.UserSuspicionByIp
|
||||||
|
val CurrentUsers = LinkedHashMap<Any?, Any?>(Inner(State0.Users, Action.battleId))
|
||||||
|
val CurrentTeams = LinkedHashMap<Any?, Any?>(Inner(State0.UsersTeam, Action.battleId))
|
||||||
|
for (User in Action.users) {
|
||||||
|
CurrentUsers[User.user] = User
|
||||||
|
CurrentTeams[User.user] = Action.team
|
||||||
|
Scores = Scores + (User.user to User.score)
|
||||||
|
Suspicion = Suspicion + (User.user to User.suspicious)
|
||||||
|
SuspicionByIp = SuspicionByIp + (User.user to User.suspiciousByIp)
|
||||||
|
}
|
||||||
|
Users = Users + (Action.battleId to CurrentUsers)
|
||||||
|
Teams = Teams + (Action.battleId to CurrentTeams)
|
||||||
|
State0.copy(
|
||||||
|
Users = Users,
|
||||||
|
UsersTeam = Teams,
|
||||||
|
UserScore = Scores,
|
||||||
|
UserSuspicion = Suspicion,
|
||||||
|
UserSuspicionByIp = SuspicionByIp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is AddUser -> ReduceBattlesSelect(
|
||||||
|
State0,
|
||||||
|
AddUsers(
|
||||||
|
battleId = Action.battleId,
|
||||||
|
users = listOf(Action.infoUser as BattleInfoUser),
|
||||||
|
team = Action.team,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
is RemoveUser -> State0.copy(
|
||||||
|
Users = State0.Users + (
|
||||||
|
Action.battleId to Inner(State0.Users, Action.battleId) - Action.userId
|
||||||
|
),
|
||||||
|
UsersTeam = State0.UsersTeam + (
|
||||||
|
Action.battleId to Inner(State0.UsersTeam, Action.battleId) - Action.userId
|
||||||
|
),
|
||||||
|
UserScore = State0.UserScore - Action.userId,
|
||||||
|
UserSuspicion = State0.UserSuspicion - Action.userId,
|
||||||
|
UserSuspicionByIp = State0.UserSuspicionByIp - Action.userId,
|
||||||
|
)
|
||||||
|
is UpdateUserScore -> State0.copy(
|
||||||
|
UserScore = State0.UserScore + (Action.userId to Action.score),
|
||||||
|
)
|
||||||
|
is UpdateUserSuspicion -> State0.copy(
|
||||||
|
UserSuspicion = State0.UserSuspicion + (Action.userId to Action.suspicious),
|
||||||
|
UserSuspicionByIp = State0.UserSuspicionByIp + (Action.userId to Action.suspiciousByIp),
|
||||||
|
)
|
||||||
|
is UpdateTeamScore -> {
|
||||||
|
val Teams = LinkedHashMap<Any?, Any?>(Inner(State0.Score, Action.battleId))
|
||||||
|
Teams[Action.team] = Action.score
|
||||||
|
State0.copy(Score = State0.Score + (Action.battleId to Teams))
|
||||||
|
}
|
||||||
|
is ResetBattlesSelect -> BattlesSelectStateSlice()
|
||||||
|
is EnterToBattleInfo ->
|
||||||
|
State0.copy(AlreadySeeBattleInfo = State0.AlreadySeeBattleInfo + Action.battleId)
|
||||||
|
is UpdateFund -> State0.copy(Fund = State0.Fund + (Action.battleId to Action.fund))
|
||||||
|
is InitProBattleRewardLimit -> State0.copy(ProLimit = Action.proLimit)
|
||||||
|
is LimitReached -> State0.copy(IsLimitReached = Action.isLimitReached)
|
||||||
|
is SetReEnterProtectBattleId -> State0.copy(ReEnterProtectBattleId = Action.battleId)
|
||||||
|
else -> State0
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
// RootReducer.kt —— 根 reducer 骨架(对应 module_10032 的根状态 z6 / TOState 与根 reducer k6)
|
||||||
//
|
//
|
||||||
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
// 原包 k6 对 89 个切片逐个调用各自的 reducer,再 `return n.cti(...)`(copy 出新状态)。
|
||||||
// 这里采用同一形状。已迁移的 80 个切片里,79 个真正调用 reducer,launchParams 只做类型收口:
|
// 这里采用同一形状。已迁移的 81 个切片里,80 个真正调用 reducer,launchParams 只做类型收口:
|
||||||
//
|
//
|
||||||
// inviteState → ReduceInvite(aD / pD.er5)
|
// inviteState → ReduceInvite(aD / pD.er5)
|
||||||
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
// loginByPassword → ReduceLoginByPassword(gD / MD.cr6)
|
||||||
@@ -82,9 +82,10 @@
|
|||||||
// battleChat → ReduceBattleChat(Q6 / Hf.wtg,根委派 `Hf.wtg(t, n.rpw_1)`)
|
// battleChat → ReduceBattleChat(Q6 / Hf.wtg,根委派 `Hf.wtg(t, n.rpw_1)`)
|
||||||
// remoteUserDataStorage → ReduceRemoteUserDataStorage($Q / vh.isl,根委派 `vh.isl(t, n.zpv_1)`)
|
// remoteUserDataStorage → ReduceRemoteUserDataStorage($Q / vh.isl,根委派 `vh.isl(t, n.zpv_1)`)
|
||||||
// matchmaking → ReduceMatchmaking(TH / JH().qrx,根委派 `JH().qrx(t, n.cpw_1)`)
|
// matchmaking → ReduceMatchmaking(TH / JH().qrx,根委派 `JH().qrx(t, n.cpw_1)`)
|
||||||
|
// battlesSelect → ReduceBattlesSelect(fA / Mi.vqk,根委派 `Mi.vqk(t, n.apw_1)`)
|
||||||
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
// launchParams → 无 reducer(原根 reducer 原样透传;默认 `ag()` = emptyMap())
|
||||||
//
|
//
|
||||||
// 其余 9 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
// 其余 8 个字段按原样透传(defaultValue 取原构造)。每个切片 reducer 对无关动作都返回原状态,
|
||||||
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
// 所以一次 copy 里串起全部已迁移 reducer,与按动作路由再归约的结果一致。
|
||||||
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
// 迁移进度与每个字段的证据见生成物 RootWiring.kt(不要手改)。
|
||||||
package App.State
|
package App.State
|
||||||
@@ -97,6 +98,7 @@ import App.State.Reducers.ReduceBattleChat
|
|||||||
import App.State.Reducers.ReduceBattleMessage
|
import App.State.Reducers.ReduceBattleMessage
|
||||||
import App.State.Reducers.ReduceBattlePause
|
import App.State.Reducers.ReduceBattlePause
|
||||||
import App.State.Reducers.ReduceBattleSearch
|
import App.State.Reducers.ReduceBattleSearch
|
||||||
|
import App.State.Reducers.ReduceBattlesSelect
|
||||||
import App.State.Reducers.ReduceBattleSettings
|
import App.State.Reducers.ReduceBattleSettings
|
||||||
import App.State.Reducers.ReduceBattleStatistics
|
import App.State.Reducers.ReduceBattleStatistics
|
||||||
import App.State.Reducers.ReduceBattleTutorial
|
import App.State.Reducers.ReduceBattleTutorial
|
||||||
@@ -261,6 +263,7 @@ object RootReducer {
|
|||||||
BattleChat = ReduceBattleChat(State0.BattleChat, Action),
|
BattleChat = ReduceBattleChat(State0.BattleChat, Action),
|
||||||
RemoteUserDataStorage = ReduceRemoteUserDataStorage(State0.RemoteUserDataStorage, Action),
|
RemoteUserDataStorage = ReduceRemoteUserDataStorage(State0.RemoteUserDataStorage, Action),
|
||||||
Matchmaking = ReduceMatchmaking(State0.Matchmaking, Action),
|
Matchmaking = ReduceMatchmaking(State0.Matchmaking, Action),
|
||||||
|
BattlesSelect = ReduceBattlesSelect(State0.BattlesSelect, Action),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import App.State.Reducers.BattleSettingsStateSlice
|
|||||||
import App.State.Reducers.BattleStatisticsStateSlice
|
import App.State.Reducers.BattleStatisticsStateSlice
|
||||||
import App.State.Reducers.BattleTutorialStateSlice
|
import App.State.Reducers.BattleTutorialStateSlice
|
||||||
import App.State.Reducers.BattleViewStateSlice
|
import App.State.Reducers.BattleViewStateSlice
|
||||||
|
import App.State.Reducers.BattlesSelectStateSlice
|
||||||
import App.State.Reducers.CaptchaStateSlice
|
import App.State.Reducers.CaptchaStateSlice
|
||||||
import App.State.Reducers.ClanChatStateSlice
|
import App.State.Reducers.ClanChatStateSlice
|
||||||
import App.State.Reducers.ClanUserInfoStateSlice
|
import App.State.Reducers.ClanUserInfoStateSlice
|
||||||
@@ -144,8 +145,8 @@ data class RootState(
|
|||||||
val Friends: FriendsStateSlice = FriendsStateSlice(),
|
val Friends: FriendsStateSlice = FriendsStateSlice(),
|
||||||
/** 原 remoteUserDataStorage($Q / vh.isl)。已迁移。 */
|
/** 原 remoteUserDataStorage($Q / vh.isl)。已迁移。 */
|
||||||
val RemoteUserDataStorage: RemoteUserDataStorageStateSlice = RemoteUserDataStorageStateSlice(),
|
val RemoteUserDataStorage: RemoteUserDataStorageStateSlice = RemoteUserDataStorageStateSlice(),
|
||||||
/** 原 battlesSelect(fA / Mi.vqk)。未迁移:原样透传。 */
|
/** 原 battlesSelect(fA / Mi.vqk)。已迁移。 */
|
||||||
val BattlesSelect: Any? = null,
|
val BattlesSelect: BattlesSelectStateSlice = BattlesSelectStateSlice(),
|
||||||
/** 原 maps(OA / Oi.sql)。已迁移。 */
|
/** 原 maps(OA / Oi.sql)。已迁移。 */
|
||||||
val Maps: MapsStateSlice = MapsStateSlice(),
|
val Maps: MapsStateSlice = MapsStateSlice(),
|
||||||
/** 原 matchmaking(TH / JH().qrx)。已迁移。 */
|
/** 原 matchmaking(TH / JH().qrx)。已迁移。 */
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ object RootWiring {
|
|||||||
SliceWiring("notifications", "xpv_1", "jJ", "B_.ise", "B_.ise(t, n.xpv_1)", listOf("AddNotification", "InitNotificationSound", "RemoveFirstNotification", "RemoveNotifications")),
|
SliceWiring("notifications", "xpv_1", "jJ", "B_.ise", "B_.ise(t, n.xpv_1)", listOf("AddNotification", "InitNotificationSound", "RemoveFirstNotification", "RemoveNotifications")),
|
||||||
SliceWiring("friends", "ypv_1", "KD", "NL().cr9", "NL().cr9(t, n.ypv_1)", listOf("AddUsersToAccepted", "AddUsersToIncoming", "AddUsersToNewAccepted", "AddUsersToNewIncoming", "ChangeFriendAddFindState", "ClearContextMenuUser", "RemoveUserFromAccepted", "RemoveUserFromIncoming", "RemoveUserFromNewAccepted", "RemoveUsersFromNewIncoming", "SetContextMenuUser", "SetLimits", "SetValidationStatus")),
|
SliceWiring("friends", "ypv_1", "KD", "NL().cr9", "NL().cr9(t, n.ypv_1)", listOf("AddUsersToAccepted", "AddUsersToIncoming", "AddUsersToNewAccepted", "AddUsersToNewIncoming", "ChangeFriendAddFindState", "ClearContextMenuUser", "RemoveUserFromAccepted", "RemoveUserFromIncoming", "RemoveUserFromNewAccepted", "RemoveUsersFromNewIncoming", "SetContextMenuUser", "SetLimits", "SetValidationStatus")),
|
||||||
SliceWiring("remoteUserDataStorage", "zpv_1", "\$Q", "vh.isl", "vh.isl(t, n.zpv_1)", listOf("UpdateClanTags", "UpdateOnlineStatus", "UpdatePremiumStatus", "UpdateRanks", "UpdateUids", "UserEnterBattle", "UserLeaveBattle", "UserLeaveGroup")),
|
SliceWiring("remoteUserDataStorage", "zpv_1", "\$Q", "vh.isl", "vh.isl(t, n.zpv_1)", listOf("UpdateClanTags", "UpdateOnlineStatus", "UpdatePremiumStatus", "UpdateRanks", "UpdateUids", "UserEnterBattle", "UserLeaveBattle", "UserLeaveGroup")),
|
||||||
SliceWiring("battlesSelect", "apw_1", "fA", "Mi.vqk", "Mi.vqk(t, n.apw_1)", listOf("?dA", "?gA", "AddBattle", "AddUser", "AddUsers", "ChangeName", "EnterToBattleInfo", "InitProBattleRewardLimit", "LimitReached", "RemoveBattle", "RemoveUser", "RoundFinish", "RoundStarted", "SetReEnterProtectBattleId", "SwapTeam", "UpdateFund", "UpdateSuspicion", "UpdateTeamScore", "UpdateUserScore", "UpdateUserSuspicion")),
|
SliceWiring("battlesSelect", "apw_1", "fA", "Mi.vqk", "Mi.vqk(t, n.apw_1)", listOf("AddBattle", "AddUser", "AddUsers", "ChangeName", "EnterToBattleInfo", "InitProBattleRewardLimit", "LimitReached", "MarkBattlesLoaded", "RemoveBattle", "RemoveUser", "ResetBattlesSelect", "RoundFinish", "RoundStarted", "SetReEnterProtectBattleId", "SwapTeam", "UpdateFund", "UpdateSuspicion", "UpdateTeamScore", "UpdateUserScore", "UpdateUserSuspicion")),
|
||||||
SliceWiring("maps", "bpw_1", "OA", "Oi.sql", "Oi.sql(t, n.bpw_1)", listOf("AddMap")),
|
SliceWiring("maps", "bpw_1", "OA", "Oi.sql", "Oi.sql(t, n.bpw_1)", listOf("AddMap")),
|
||||||
SliceWiring("matchmaking", "cpw_1", "TH", "JH().qrx", "JH().qrx(t, n.cpw_1)", listOf("CancelLoadingBattle", "Configure", "EnterToBattleApply", "Play", "ResetMatchmakingProgress", "SelectMatchmakingMode", "SetRankIndexToMinGS", "StartLoadingBattle", "WasRegistered")),
|
SliceWiring("matchmaking", "cpw_1", "TH", "JH().qrx", "JH().qrx(t, n.cpw_1)", listOf("CancelLoadingBattle", "Configure", "EnterToBattleApply", "Play", "ResetMatchmakingProgress", "SelectMatchmakingMode", "SetRankIndexToMinGS", "StartLoadingBattle", "WasRegistered")),
|
||||||
SliceWiring("battleCreateState", "dpw_1", "\$6", "Df.ttg", "Df.ttg(t, n.dpw_1, n.bpw_1, n.ypu_1)", listOf("?A6", "?B6", "?C6", "?D6", "?E6", "?F6", "?I6", "?L6", "?M6", "?N6", "?P6", "?R6", "?T6", "?U6", "Configure", "CreateBattle", "SetRestrictions")),
|
SliceWiring("battleCreateState", "dpw_1", "\$6", "Df.ttg", "Df.ttg(t, n.dpw_1, n.bpw_1, n.ypu_1)", listOf("?A6", "?B6", "?C6", "?D6", "?E6", "?F6", "?I6", "?L6", "?M6", "?N6", "?P6", "?R6", "?T6", "?U6", "Configure", "CreateBattle", "SetRestrictions")),
|
||||||
@@ -106,7 +106,7 @@ object RootWiring {
|
|||||||
)
|
)
|
||||||
|
|
||||||
/** 已迁移(强类型;launchParams 为透传,不调用 reducer)的字段。 */
|
/** 已迁移(强类型;launchParams 为透传,不调用 reducer)的字段。 */
|
||||||
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState", "friends", "suppliesState", "clanUserInfo", "battleInviteState", "partner", "userRenameState", "battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial", "clanChatState", "battleSearchState", "battleStatistics", "soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings", "graphicsSettings", "controlSettings", "battleSettings", "contractState", "tankBuilderState", "battleMessage", "maps", "battleChat", "remoteUserDataStorage", "matchmaking")
|
val Migrated: Set<String> = setOf("inviteState", "loginByPassword", "twitchState", "home", "localBattleUserState", "shop", "screen", "lootBoxes", "garage", "garagePreview", "entrance", "user", "settings", "accountSettings", "proBattle", "language", "announcement", "launchParams", "news", "notifications", "quests", "lobbyLoader", "purchaseDialogState", "promoCode", "supportUrl", "rulesUpdated", "notificationByCountry", "availabilityByRank", "icons", "questCategories", "mainQuest", "securitySettings", "referralEvent", "tipsState", "rankUpDialogState", "battleResult", "captchaState", "modalScreen", "droppableGold", "eventGoods", "creatorTagState", "rewardedVideosState", "passwordChangeState", "system", "contextTutorial", "battleTutorial", "spectator", "twoStepVerificationState", "antiAddiction", "moderation", "migrationState", "register", "userReportsState", "friends", "suppliesState", "clanUserInfo", "battleInviteState", "partner", "userRenameState", "battlePauseState", "battleViewState", "tankActionsLogState", "suppliesTutorial", "clanChatState", "battleSearchState", "battleStatistics", "soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings", "graphicsSettings", "controlSettings", "battleSettings", "contractState", "tankBuilderState", "battleMessage", "maps", "battleChat", "remoteUserDataStorage", "matchmaking", "battlesSelect")
|
||||||
|
|
||||||
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
/** 未迁移字段:归约时原样透传,作为后续迁移清单。 */
|
||||||
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
val Unmigrated: List<SliceWiring> get() = All.filter { it.Field !in Migrated }
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
// System / ContextTutorial / BattleTutorial / Spectator / TwoStepVerification / AntiAddiction /
|
||||||
// Moderation / MigrationState / Register / UserReports /
|
// Moderation / MigrationState / Register / UserReports /
|
||||||
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename /
|
// Friends / Supplies / ClanUserInfo / BattleInvite / Partner / UserRename /
|
||||||
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings / GraphicsSettings / ControlSettings / BattleSettings / ContractState / TankBuilder / BattleMessage / Maps / BattleChat / RemoteUserDataStorage / Matchmaking;
|
// BattlePause / BattleView / TankActionsLog / SuppliesTutorial / ClanChat / BattleSearch / BattleStatistics / SoundSettings / GameSettings / KeyboardSettings / TouchscreenHudSettings / GraphicsSettings / ControlSettings / BattleSettings / ContractState / TankBuilder / BattleMessage / Maps / BattleChat / RemoteUserDataStorage / Matchmaking / BattlesSelect;
|
||||||
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
// ㉑ launchParams 是纯透传切片(无 reducer/动作),只做 Map 类型收口;⑭ 根 reducer 的 89 槽位委派
|
||||||
//
|
//
|
||||||
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
// 用法:$env:TANKIOFFLINE_STATE_TEST='1'; node …(见 TankiOffline/tools/RunStateTest.ps1)
|
||||||
@@ -767,6 +767,30 @@ import App.State.Reducers.MatchmakingStateSlice
|
|||||||
import App.State.Reducers.ReduceMatchmaking
|
import App.State.Reducers.ReduceMatchmaking
|
||||||
import App.State.Reducers.ResetMatchmakingProgress
|
import App.State.Reducers.ResetMatchmakingProgress
|
||||||
import App.State.Reducers.StartLoadingBattle
|
import App.State.Reducers.StartLoadingBattle
|
||||||
|
import App.State.AddBattle
|
||||||
|
import App.State.AddUser
|
||||||
|
import App.State.AddUsers
|
||||||
|
import App.State.BattleCreateParameters
|
||||||
|
import App.State.BattleInfoUser
|
||||||
|
import App.State.BattleParams
|
||||||
|
import App.State.ChangeName
|
||||||
|
import App.State.EnterToBattleInfo
|
||||||
|
import App.State.InitProBattleRewardLimit
|
||||||
|
import App.State.LimitReached
|
||||||
|
import App.State.ProBattleRewardLimitData
|
||||||
|
import App.State.RemoveUser
|
||||||
|
import App.State.RoundFinish
|
||||||
|
import App.State.RoundStarted
|
||||||
|
import App.State.SetReEnterProtectBattleId
|
||||||
|
import App.State.SwapTeam
|
||||||
|
import App.State.UpdateSuspicion
|
||||||
|
import App.State.UpdateTeamScore
|
||||||
|
import App.State.UpdateUserScore
|
||||||
|
import App.State.UpdateUserSuspicion
|
||||||
|
import App.State.Reducers.BattlesSelectStateSlice
|
||||||
|
import App.State.Reducers.MarkBattlesLoaded
|
||||||
|
import App.State.Reducers.ReduceBattlesSelect
|
||||||
|
import App.State.Reducers.ResetBattlesSelect
|
||||||
import App.State.Reducers.UserRankBounds
|
import App.State.Reducers.UserRankBounds
|
||||||
import App.State.Reducers.UserStateSlice
|
import App.State.Reducers.UserStateSlice
|
||||||
import App.State.Reducers.ClearHullData
|
import App.State.Reducers.ClearHullData
|
||||||
@@ -1194,7 +1218,7 @@ object StateCheck {
|
|||||||
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
Check("切片 LocalBattleUser:接 Store 派发后状态已归约", Store.State.IsReArmorTemporaryDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ⑭ 根 reducer:89 个槽位的委派表 + 80 个已迁移切片(79 归约 + launchParams 透传)
|
// ⑭ 根 reducer:89 个槽位的委派表 + 81 个已迁移切片(80 归约 + launchParams 透传)
|
||||||
run {
|
run {
|
||||||
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
Check("根:根状态 89 个切片槽位", RootWiring.All.size == 89)
|
||||||
Check(
|
Check(
|
||||||
@@ -1258,7 +1282,7 @@ object StateCheck {
|
|||||||
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
LocalBattleW.Reducer == "(inline@localBattleUserState)"
|
||||||
)
|
)
|
||||||
Check(
|
Check(
|
||||||
"根:迁移表 = 80 个已迁移字段,其余 9 个待迁",
|
"根:迁移表 = 81 个已迁移字段,其余 8 个待迁",
|
||||||
RootReducer.Migrated ==
|
RootReducer.Migrated ==
|
||||||
setOf(
|
setOf(
|
||||||
"inviteState", "loginByPassword", "twitchState", "home",
|
"inviteState", "loginByPassword", "twitchState", "home",
|
||||||
@@ -1282,9 +1306,9 @@ object StateCheck {
|
|||||||
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
"soundSettings", "gameSettings", "keyboardSettings", "touchscreenHudSettings",
|
||||||
"graphicsSettings", "controlSettings", "battleSettings", "contractState",
|
"graphicsSettings", "controlSettings", "battleSettings", "contractState",
|
||||||
"tankBuilderState", "battleMessage", "maps", "battleChat",
|
"tankBuilderState", "battleMessage", "maps", "battleChat",
|
||||||
"remoteUserDataStorage", "matchmaking",
|
"remoteUserDataStorage", "matchmaking", "battlesSelect",
|
||||||
) &&
|
) &&
|
||||||
RootWiring.Unmigrated.size == 9
|
RootWiring.Unmigrated.size == 8
|
||||||
)
|
)
|
||||||
|
|
||||||
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
// 一次 ReduceRoot 里多个切片各归约自己的动作,互不串片
|
||||||
@@ -1340,7 +1364,7 @@ object StateCheck {
|
|||||||
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
S5.User.Uid == "user-1" && S5.Screen.Current == NamedScreen("Preloader")
|
||||||
)
|
)
|
||||||
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
Check("根:无关动作返回等值状态", ReduceRoot(S5, AddFrags(1)) == S5)
|
||||||
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 80/89")
|
Check("根:Coverage 文本", RootReducer.Coverage == "已迁移 81/89")
|
||||||
|
|
||||||
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
val Store = ReduxStore(RootState(), { S, A -> ReduceRoot(S, A) })
|
||||||
Store.Dispatch(SetStatus("LOGGING_IN"))
|
Store.Dispatch(SetStatus("LOGGING_IN"))
|
||||||
@@ -6652,6 +6676,127 @@ object StateCheck {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 91 切片 reducer:BattlesSelect(fA / Mi.vqk,15 字段;20 个动作)
|
||||||
|
run {
|
||||||
|
fun Params(): BattleCreateParameters = BattleCreateParameters(
|
||||||
|
battleMode = "DM", battleModeForMatchmaking = null,
|
||||||
|
battleOptions = listOf("VALUABLE"), crossPlayMode = "", formatMode = "fmt",
|
||||||
|
limits = "10", timeLimitInSec = "600", mapId = 1L, maxPeopleCount = 8,
|
||||||
|
name = "b1", proBattle = true, rankRange = "1-5", min = "1", theme = "2",
|
||||||
|
)
|
||||||
|
|
||||||
|
val S0 = BattlesSelectStateSlice()
|
||||||
|
Check("切片 BattlesSelect:默认值完整", !S0.Loaded && S0.Battles.isEmpty())
|
||||||
|
val S1 = ReduceBattlesSelect(S0, AddBattle(1L, 99L, Params(), "LOW"))
|
||||||
|
val Battle = S1.Battles[1L] as BattleParams
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:AddBattle 建列表项与四个子表",
|
||||||
|
Battle.name == "b1" && Battle.mapId == 1L && Battle.proBattle &&
|
||||||
|
Battle.parkourMode == false && S1.Users[1L] == emptyMap<Any?, Any?>() &&
|
||||||
|
S1.Score[1L] == emptyMap<Any?, Any?>() && S1.Creators[1L] == 99L
|
||||||
|
)
|
||||||
|
val S2 = ReduceBattlesSelect(S1, RoundStarted(1L, 60))
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:RoundStarted 写回合计时并清分数",
|
||||||
|
S2.RoundEndTimes[1L] == 60 && S2.Score[1L] == emptyMap<Any?, Any?>()
|
||||||
|
)
|
||||||
|
val S3 = ReduceBattlesSelect(S2, UpdateTeamScore(1L, "RED", 3))
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:UpdateTeamScore 写队伍分",
|
||||||
|
(S3.Score[1L] as Map<Any?, Any?>)["RED"] == 3
|
||||||
|
)
|
||||||
|
val S4 = ReduceBattlesSelect(
|
||||||
|
S3,
|
||||||
|
AddUsers(1L, listOf(BattleInfoUser(0L, 0, false, false, 7L)), "RED"),
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:AddUsers 写用户 / 队伍 / 个人分",
|
||||||
|
(S4.Users[1L] as Map<Any?, Any?>).keys == setOf<Any?>(7L) &&
|
||||||
|
(S4.UsersTeam[1L] as Map<Any?, Any?>)[7L] == "RED" &&
|
||||||
|
S4.UserScore[7L] == 0
|
||||||
|
)
|
||||||
|
val S5 = ReduceBattlesSelect(
|
||||||
|
ReduceBattlesSelect(S4, UpdateUserScore(1L, 7L, 9)),
|
||||||
|
UpdateUserSuspicion(1L, 7L, true, false),
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:个人分与可疑标记",
|
||||||
|
S5.UserScore[7L] == 9 && S5.UserSuspicion[7L] == true &&
|
||||||
|
S5.UserSuspicionByIp[7L] == false
|
||||||
|
)
|
||||||
|
val S6 = ReduceBattlesSelect(S5, SwapTeam(1L))
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:SwapTeam 换队并把该用户分数归零",
|
||||||
|
(S6.UsersTeam[1L] as Map<Any?, Any?>)[7L] == "BLUE" && S6.UserScore[7L] == 0
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:ChangeName / UpdateSuspicion",
|
||||||
|
(ReduceBattlesSelect(S1, ChangeName(1L, "renamed"))
|
||||||
|
.Battles[1L] as BattleParams).name == "renamed" &&
|
||||||
|
(ReduceBattlesSelect(S1, UpdateSuspicion(1L, "HIGH"))
|
||||||
|
.Battles[1L] as BattleParams).suspicionLevel == "HIGH"
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:EnterToBattleInfo / UpdateFund / LimitReached",
|
||||||
|
ReduceBattlesSelect(S1, EnterToBattleInfo(1L))
|
||||||
|
.AlreadySeeBattleInfo == setOf<Any?>(1L) &&
|
||||||
|
ReduceBattlesSelect(S1, UpdateFund(1L, 20)).Fund[1L] == 20 &&
|
||||||
|
ReduceBattlesSelect(S1, LimitReached(true)).IsLimitReached
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:InitProBattleRewardLimit / SetReEnterProtectBattleId",
|
||||||
|
ReduceBattlesSelect(
|
||||||
|
S1,
|
||||||
|
InitProBattleRewardLimit(ProBattleRewardLimitData(1, 2, 3, 4)),
|
||||||
|
).ProLimit == ProBattleRewardLimitData(1, 2, 3, 4) &&
|
||||||
|
ReduceBattlesSelect(S1, SetReEnterProtectBattleId(5L))
|
||||||
|
.ReEnterProtectBattleId == 5L
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:RemoveUser 清四个个人表",
|
||||||
|
ReduceBattlesSelect(S5, RemoveUser(1L, 7L)).let {
|
||||||
|
(it.Users[1L] as Map<Any?, Any?>).isEmpty() &&
|
||||||
|
it.UserScore[7L] == null && it.UserSuspicion[7L] == null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:RemoveBattle 清四个战斗表",
|
||||||
|
ReduceBattlesSelect(
|
||||||
|
ReduceBattlesSelect(S5, EnterToBattleInfo(1L)),
|
||||||
|
RemoveBattle(1L),
|
||||||
|
).let {
|
||||||
|
it.Battles.isEmpty() && it.Users.isEmpty() && it.Creators.isEmpty() &&
|
||||||
|
it.AlreadySeeBattleInfo.isEmpty()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:RoundFinish 删计时与资金",
|
||||||
|
ReduceBattlesSelect(ReduceBattlesSelect(S2, UpdateFund(1L, 5)), RoundFinish(1L))
|
||||||
|
.let { it.RoundEndTimes[1L] == null && it.Fund[1L] == null }
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:MarkBattlesLoaded / ResetBattlesSelect",
|
||||||
|
ReduceBattlesSelect(S0, MarkBattlesLoaded).Loaded &&
|
||||||
|
ReduceBattlesSelect(S5, ResetBattlesSelect) == BattlesSelectStateSlice()
|
||||||
|
)
|
||||||
|
Check(
|
||||||
|
"切片 BattlesSelect:无关动作不改状态",
|
||||||
|
ReduceBattlesSelect(S5, AddFrags(1)) == S5
|
||||||
|
)
|
||||||
|
|
||||||
|
val Root0 = RootState()
|
||||||
|
val Root1 = ReduceRoot(Root0, MarkBattlesLoaded)
|
||||||
|
Check(
|
||||||
|
"根:MarkBattlesLoaded 只动 battlesSelect",
|
||||||
|
Root1.BattlesSelect.Loaded && Root1.Matchmaking == Root0.Matchmaking
|
||||||
|
)
|
||||||
|
val W = RootWiring.ByField("battlesSelect")!!
|
||||||
|
Check(
|
||||||
|
"根:battlesSelect 委派到 fA / Mi.vqk 且 20 个动作",
|
||||||
|
W.SliceClass == "fA" && W.Reducer == "Mi.vqk" && W.Actions.size == 20
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val Failed = Results.filter { !it.second }
|
val Failed = Results.filter { !it.second }
|
||||||
println("TankiOffline 状态层自检:${Results.size} 项")
|
println("TankiOffline 状态层自检:${Results.size} 项")
|
||||||
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)
|
for ((Name, Ok) in Results) println((if (Ok) " ✓ " else " ✗ ") + Name)
|
||||||
|
|||||||
Reference in new issue
Block a user