volleyballsimtypes 0.0.488 → 0.0.491
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/api/index.d.ts +2 -2
- package/dist/cjs/src/data/models/tactics.d.ts +2 -2
- package/dist/cjs/src/data/transformers/tactics.test.js +19 -0
- package/dist/cjs/src/service/notification/catalog/en.json +2 -2
- package/dist/cjs/src/service/notification/catalog/es.json +2 -2
- package/dist/cjs/src/service/notification/catalog/fr.json +2 -2
- package/dist/cjs/src/service/notification/catalog/it.json +2 -2
- package/dist/cjs/src/service/notification/catalog/pl.json +2 -2
- package/dist/cjs/src/service/notification/catalog/pt-BR.json +2 -2
- package/dist/cjs/src/service/notification/catalog/tr.json +2 -2
- package/dist/cjs/src/service/notification/registry.js +2 -1
- package/dist/cjs/src/service/team/blocking-preference.d.ts +3 -1
- package/dist/cjs/src/service/team/blocking-preference.js +7 -0
- package/dist/cjs/src/service/team/schemas/tactics.z.d.ts +2 -2
- package/dist/cjs/src/service/team/schemas/tactics.z.js +7 -2
- package/dist/cjs/src/service/team/schemas/tactics.z.test.js +32 -0
- package/dist/cjs/src/service/team/schemas/team.z.d.ts +2 -2
- package/dist/esm/src/api/index.d.ts +2 -2
- package/dist/esm/src/data/models/tactics.d.ts +2 -2
- package/dist/esm/src/data/transformers/tactics.test.js +20 -1
- package/dist/esm/src/service/notification/catalog/en.json +2 -2
- package/dist/esm/src/service/notification/catalog/es.json +2 -2
- package/dist/esm/src/service/notification/catalog/fr.json +2 -2
- package/dist/esm/src/service/notification/catalog/it.json +2 -2
- package/dist/esm/src/service/notification/catalog/pl.json +2 -2
- package/dist/esm/src/service/notification/catalog/pt-BR.json +2 -2
- package/dist/esm/src/service/notification/catalog/tr.json +2 -2
- package/dist/esm/src/service/notification/registry.js +2 -1
- package/dist/esm/src/service/team/blocking-preference.d.ts +3 -1
- package/dist/esm/src/service/team/blocking-preference.js +6 -1
- package/dist/esm/src/service/team/schemas/tactics.z.d.ts +2 -2
- package/dist/esm/src/service/team/schemas/tactics.z.js +7 -2
- package/dist/esm/src/service/team/schemas/tactics.z.test.js +32 -0
- package/dist/esm/src/service/team/schemas/team.z.d.ts +2 -2
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BoxScore, DataProps, DeclineStatus, Division as _Division, League as _League, Match as _Match, MatchSet as _MatchSet, Player as _Player, PlayerPosition, Qualifier as _Qualifier, QualifierMatch as _QualifierMatch, Rally as _Rally, RallyEvent as _RallyEvent, PointBreakdown, RallyMetrics, Season as _Season, Standing as _Standing, Team as _Team, Tournament as _Tournament, TournamentMatch as _TournamentMatch, National as _National, NationalMatch as _NationalMatch, Country as _Country, CourtPosition, ConditionLogic, EnergyBand, MatchForfeitType, PerformanceStats, PinchCondition,
|
|
1
|
+
import { BoxScore, DataProps, DeclineStatus, Division as _Division, League as _League, Match as _Match, MatchSet as _MatchSet, Player as _Player, PlayerPosition, Qualifier as _Qualifier, QualifierMatch as _QualifierMatch, Rally as _Rally, RallyEvent as _RallyEvent, PointBreakdown, RallyMetrics, Season as _Season, Standing as _Standing, Team as _Team, Tournament as _Tournament, TournamentMatch as _TournamentMatch, National as _National, NationalMatch as _NationalMatch, Country as _Country, BlockingAssignment, CourtPosition, ConditionLogic, EnergyBand, MatchForfeitType, PerformanceStats, PinchCondition, RotationSystemEnum, SubBackMode, SubBand } from '../service';
|
|
2
2
|
export type Rally = DataProps<_Rally> & {
|
|
3
3
|
homePlayerPosition: PlayerPosition[];
|
|
4
4
|
awayPlayerPosition: PlayerPosition[];
|
|
@@ -101,7 +101,7 @@ export interface ApiOffensivePreference {
|
|
|
101
101
|
}
|
|
102
102
|
export interface ApiBlockingPreference {
|
|
103
103
|
rotation: number;
|
|
104
|
-
targets: Record<string,
|
|
104
|
+
targets: Record<string, BlockingAssignment>;
|
|
105
105
|
}
|
|
106
106
|
export interface ApiSystemSet {
|
|
107
107
|
rotationSystem: RotationSystemEnum;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model, Optional } from 'sequelize';
|
|
3
3
|
import { PlayerId, TeamId, TeamModel } from '.';
|
|
4
|
-
import { ConditionLogic, CourtPosition, EnergyBand, PinchCondition,
|
|
4
|
+
import { BlockingAssignment, ConditionLogic, CourtPosition, EnergyBand, PinchCondition, RotationSystemEnum, SubBackMode, SubBand, SubMode } from '../../service';
|
|
5
5
|
export interface TacticsLineupAttributes {
|
|
6
6
|
[CourtPosition.LIBERO_ZONE]?: PlayerId;
|
|
7
7
|
[CourtPosition.LEFT_BACK]: PlayerId;
|
|
@@ -36,7 +36,7 @@ export interface OffensivePreferenceAttributes {
|
|
|
36
36
|
}
|
|
37
37
|
export interface BlockingPreferenceAttributes {
|
|
38
38
|
rotation: number;
|
|
39
|
-
targets: Record<PlayerId,
|
|
39
|
+
targets: Record<PlayerId, BlockingAssignment>;
|
|
40
40
|
}
|
|
41
41
|
export interface SystemSetAttributes {
|
|
42
42
|
rotationSystem: RotationSystemEnum;
|
|
@@ -216,6 +216,25 @@ function makeTactics(designatedSubs) {
|
|
|
216
216
|
const back = (0, tactics_1.transformToTactics)(attrs, roster);
|
|
217
217
|
(0, globals_1.expect)(back.blockingPreferences[0].targets).toEqual({ [p4.id]: service_1.RoleEnum.OUTSIDE_HITTER, [p3.id]: service_1.RoleEnum.MIDDLE_BLOCKER });
|
|
218
218
|
});
|
|
219
|
+
// NO_BLOCK rides in the same targets map as a commit assignment, so the transformers copy it wholesale with no
|
|
220
|
+
// mapping code. This pins that: the sentinel must survive the row round-trip verbatim, mixed with a commit, and
|
|
221
|
+
// in the per-set overrides. If it ever gets translated or dropped, a player silently starts blocking again.
|
|
222
|
+
(0, globals_1.it)('round-trips a NO_BLOCK assignment, mixed with a commit and in per-set overrides', () => {
|
|
223
|
+
const withNoBlock = service_1.Tactics.create({
|
|
224
|
+
lineup: { 4: p4, 3: p3, 2: p2, 5: p5, 6: p6, 1: p1, bench: [] },
|
|
225
|
+
liberoReplacements: [],
|
|
226
|
+
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: service_1.NO_BLOCK, [p3.id]: service_1.RoleEnum.MIDDLE_BLOCKER } }],
|
|
227
|
+
blockingPreferenceSets: [[{ rotation: 2, targets: { [p2.id]: service_1.NO_BLOCK } }]]
|
|
228
|
+
});
|
|
229
|
+
const attrs = (0, tactics_1.transformFromTactics)(withNoBlock, 'team-1');
|
|
230
|
+
(0, globals_1.expect)(attrs.blocking_preferences).toEqual([
|
|
231
|
+
{ rotation: 1, targets: { [p4.id]: service_1.NO_BLOCK, [p3.id]: service_1.RoleEnum.MIDDLE_BLOCKER } }
|
|
232
|
+
]);
|
|
233
|
+
(0, globals_1.expect)(attrs.blocking_preference_sets).toEqual([[{ rotation: 2, targets: { [p2.id]: service_1.NO_BLOCK } }]]);
|
|
234
|
+
const back = (0, tactics_1.transformToTactics)(attrs, roster);
|
|
235
|
+
(0, globals_1.expect)(back.blockingPreferences[0].targets).toEqual({ [p4.id]: service_1.NO_BLOCK, [p3.id]: service_1.RoleEnum.MIDDLE_BLOCKER });
|
|
236
|
+
(0, globals_1.expect)(back.blockingPreferenceSets?.[0][0].targets).toEqual({ [p2.id]: service_1.NO_BLOCK });
|
|
237
|
+
});
|
|
219
238
|
});
|
|
220
239
|
(0, globals_1.describe)('libero injuries — service <-> row round-trip + lenient heal', () => {
|
|
221
240
|
const country = (0, test_helpers_1.makeCountry)();
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Your team has been promoted to a higher division."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Daily reward
|
|
31
|
-
"body": "Your daily
|
|
30
|
+
"title": "Daily reward ready",
|
|
31
|
+
"body": "Your daily reward is ready to claim!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Welcome to World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Tu equipo ha ascendido a una división superior."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Recompensa diaria
|
|
31
|
-
"body": "Tu recompensa
|
|
30
|
+
"title": "Recompensa diaria lista",
|
|
31
|
+
"body": "¡Tu recompensa diaria está lista para reclamar!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Te damos la bienvenida a World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Votre équipe a été promue dans une division supérieure."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Récompense quotidienne
|
|
31
|
-
"body": "Votre récompense
|
|
30
|
+
"title": "Récompense quotidienne prête",
|
|
31
|
+
"body": "Votre récompense quotidienne est prête à être récupérée !"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Bienvenue sur World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "La tua squadra è stata promossa in una divisione superiore."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Ricompensa giornaliera
|
|
31
|
-
"body": "La tua ricompensa
|
|
30
|
+
"title": "Ricompensa giornaliera pronta",
|
|
31
|
+
"body": "La tua ricompensa giornaliera è pronta da riscattare!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Benvenuto in World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Twoja drużyna awansowała do wyższej dywizji."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "
|
|
31
|
-
"body": "Twoja codzienna nagroda
|
|
30
|
+
"title": "Codzienna nagroda gotowa",
|
|
31
|
+
"body": "Twoja codzienna nagroda jest gotowa do odebrania!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Witaj w World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Seu time foi promovido para uma divisão superior."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Recompensa diária
|
|
31
|
-
"body": "Sua recompensa
|
|
30
|
+
"title": "Recompensa diária pronta",
|
|
31
|
+
"body": "Sua recompensa diária está pronta para coletar!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Boas-vindas ao World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Takımın bir üst gruba terfi etti."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Günlük ödül
|
|
31
|
-
"body": "Günlük
|
|
30
|
+
"title": "Günlük ödül hazır",
|
|
31
|
+
"body": "Günlük ödülün alınmaya hazır!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "World Aces'e hoş geldin",
|
|
@@ -90,7 +90,8 @@ exports.NOTIFICATION_REGISTRY = {
|
|
|
90
90
|
},
|
|
91
91
|
DAILY_LOGIN: {
|
|
92
92
|
emitsPush: true,
|
|
93
|
-
|
|
93
|
+
// Fires when the reward becomes claimable (00:00 UTC), so it opens the daily-login claim view.
|
|
94
|
+
deepLink: () => '/daily-login',
|
|
94
95
|
pushTitleKey: 'dailyLogin.title',
|
|
95
96
|
pushBodyKey: 'dailyLogin.body',
|
|
96
97
|
inAppMessageKey: 'dailyLogin.body',
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { LineupFunction } from './lineup-function';
|
|
2
|
+
export declare const NO_BLOCK: "NO_BLOCK";
|
|
3
|
+
export type BlockingAssignment = LineupFunction | typeof NO_BLOCK;
|
|
2
4
|
export interface BlockingPreference {
|
|
3
5
|
readonly rotation: number;
|
|
4
|
-
readonly targets: Record<string,
|
|
6
|
+
readonly targets: Record<string, BlockingAssignment>;
|
|
5
7
|
}
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NO_BLOCK = void 0;
|
|
4
|
+
// A front-row player opted OUT of blocking for this rotation. They never join the wall under any circumstance:
|
|
5
|
+
// not as the lead blocker (the lane's next-nearest front-row player leads instead), not as a side blocker, and
|
|
6
|
+
// no trait can coerce them in -- MOVING_WALL's guaranteed lead hand, its beaten-read hand and its side-joiner
|
|
7
|
+
// roll are all suppressed, as is a dedicated-blocking commit. Sits in the same `targets` map as a commit
|
|
8
|
+
// assignment, so the two are mutually exclusive by construction: a player is reading, committed, or out.
|
|
9
|
+
exports.NO_BLOCK = 'NO_BLOCK';
|
|
@@ -281,11 +281,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
|
|
|
281
281
|
}, z.core.$strip>>>>;
|
|
282
282
|
blockingPreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
283
283
|
rotation: z.ZodNumber;
|
|
284
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum
|
|
284
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
285
285
|
}, z.core.$strip>>>;
|
|
286
286
|
blockingPreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
287
287
|
rotation: z.ZodNumber;
|
|
288
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum
|
|
288
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
289
289
|
}, z.core.$strip>>>>;
|
|
290
290
|
replaceKnockedImmediately: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
291
291
|
injuryReplacements: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TacticsInputSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const player_1 = require("../../player");
|
|
6
|
+
const blocking_preference_1 = require("../blocking-preference");
|
|
6
7
|
const energy_band_1 = require("../energy-band");
|
|
7
8
|
const rotation_system_1 = require("../rotation-system");
|
|
8
9
|
const designated_sub_z_1 = require("./designated-sub.z");
|
|
@@ -59,8 +60,12 @@ const offensivePreferenceSchema = zod_1.z.object({
|
|
|
59
60
|
weights: zod_1.z.record(zod_1.z.string(), zod_1.z.number().int().min(0)),
|
|
60
61
|
tempos: zod_1.z.record(zod_1.z.string(), tempoPreferenceSchema).optional()
|
|
61
62
|
});
|
|
62
|
-
//
|
|
63
|
-
|
|
63
|
+
// What a front-row starter can be assigned: an opposing attacking function to commit to (every RoleEnum except
|
|
64
|
+
// the libero, which never attacks), or NO_BLOCK to sit the rotation out of the block entirely.
|
|
65
|
+
const blockingFunctionSchema = zod_1.z.union([
|
|
66
|
+
zod_1.z.nativeEnum(player_1.RoleEnum).refine((v) => v !== player_1.RoleEnum.LIBERO, { message: 'BLOCKING_TARGET_CANNOT_BE_LIBERO' }),
|
|
67
|
+
zod_1.z.literal(blocking_preference_1.NO_BLOCK)
|
|
68
|
+
]);
|
|
64
69
|
// One rotation's dedicated-blocking assignments: `targets` maps my front-row starter ids to the opposing function
|
|
65
70
|
// each commits to block. Cross-field checks (keys are starters) live in the superRefine below.
|
|
66
71
|
const blockingPreferenceSchema = zod_1.z.object({
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const globals_1 = require("@jest/globals");
|
|
4
4
|
const tactics_z_1 = require("./tactics.z");
|
|
5
|
+
const blocking_preference_1 = require("../blocking-preference");
|
|
5
6
|
const player_1 = require("../../player");
|
|
6
7
|
const test_helpers_1 = require("../../test-helpers");
|
|
7
8
|
(0, globals_1.describe)('TacticsInputSchema — second libero rules', () => {
|
|
@@ -280,4 +281,35 @@ const test_helpers_1 = require("../../test-helpers");
|
|
|
280
281
|
}));
|
|
281
282
|
(0, globals_1.expect)(res.success).toBe(true);
|
|
282
283
|
});
|
|
284
|
+
(0, globals_1.it)('accepts NO_BLOCK as an assignment, alongside a commit on another starter', () => {
|
|
285
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
286
|
+
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: blocking_preference_1.NO_BLOCK, [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } }]
|
|
287
|
+
}));
|
|
288
|
+
(0, globals_1.expect)(res.success).toBe(true);
|
|
289
|
+
if (res.success) {
|
|
290
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets[p4.id]).toBe(blocking_preference_1.NO_BLOCK);
|
|
291
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets[p3.id]).toBe(player_1.RoleEnum.MIDDLE_BLOCKER);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
(0, globals_1.it)('accepts NO_BLOCK in a per-set override', () => {
|
|
295
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
296
|
+
blockingPreferenceSets: [[{ rotation: 1, targets: { [p4.id]: blocking_preference_1.NO_BLOCK } }], []]
|
|
297
|
+
}));
|
|
298
|
+
(0, globals_1.expect)(res.success).toBe(true);
|
|
299
|
+
});
|
|
300
|
+
(0, globals_1.it)('still rejects a NO_BLOCK assignment on a player who is not a starter', () => {
|
|
301
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
302
|
+
blockingPreferences: [{ rotation: 1, targets: { [reserve.id]: blocking_preference_1.NO_BLOCK } }]
|
|
303
|
+
}));
|
|
304
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
305
|
+
if (!res.success) {
|
|
306
|
+
(0, globals_1.expect)(res.error.issues.some(i => i.message === 'BLOCKING_PREFERENCE_BLOCKER_NOT_A_STARTER')).toBe(true);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
(0, globals_1.it)('rejects an unknown assignment string', () => {
|
|
310
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
311
|
+
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: 'NO_BLOCKING' } }]
|
|
312
|
+
}));
|
|
313
|
+
(0, globals_1.expect)(res.success).toBe(false);
|
|
314
|
+
});
|
|
283
315
|
});
|
|
@@ -289,11 +289,11 @@ export declare const TeamInputSchema: z.ZodObject<{
|
|
|
289
289
|
}, z.core.$strip>>>>;
|
|
290
290
|
blockingPreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
291
291
|
rotation: z.ZodNumber;
|
|
292
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum
|
|
292
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
293
293
|
}, z.core.$strip>>>;
|
|
294
294
|
blockingPreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
295
295
|
rotation: z.ZodNumber;
|
|
296
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum
|
|
296
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
297
297
|
}, z.core.$strip>>>>;
|
|
298
298
|
replaceKnockedImmediately: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
299
299
|
injuryReplacements: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BoxScore, DataProps, DeclineStatus, Division as _Division, League as _League, Match as _Match, MatchSet as _MatchSet, Player as _Player, PlayerPosition, Qualifier as _Qualifier, QualifierMatch as _QualifierMatch, Rally as _Rally, RallyEvent as _RallyEvent, PointBreakdown, RallyMetrics, Season as _Season, Standing as _Standing, Team as _Team, Tournament as _Tournament, TournamentMatch as _TournamentMatch, National as _National, NationalMatch as _NationalMatch, Country as _Country, CourtPosition, ConditionLogic, EnergyBand, MatchForfeitType, PerformanceStats, PinchCondition,
|
|
1
|
+
import { BoxScore, DataProps, DeclineStatus, Division as _Division, League as _League, Match as _Match, MatchSet as _MatchSet, Player as _Player, PlayerPosition, Qualifier as _Qualifier, QualifierMatch as _QualifierMatch, Rally as _Rally, RallyEvent as _RallyEvent, PointBreakdown, RallyMetrics, Season as _Season, Standing as _Standing, Team as _Team, Tournament as _Tournament, TournamentMatch as _TournamentMatch, National as _National, NationalMatch as _NationalMatch, Country as _Country, BlockingAssignment, CourtPosition, ConditionLogic, EnergyBand, MatchForfeitType, PerformanceStats, PinchCondition, RotationSystemEnum, SubBackMode, SubBand } from '../service';
|
|
2
2
|
export type Rally = DataProps<_Rally> & {
|
|
3
3
|
homePlayerPosition: PlayerPosition[];
|
|
4
4
|
awayPlayerPosition: PlayerPosition[];
|
|
@@ -101,7 +101,7 @@ export interface ApiOffensivePreference {
|
|
|
101
101
|
}
|
|
102
102
|
export interface ApiBlockingPreference {
|
|
103
103
|
rotation: number;
|
|
104
|
-
targets: Record<string,
|
|
104
|
+
targets: Record<string, BlockingAssignment>;
|
|
105
105
|
}
|
|
106
106
|
export interface ApiSystemSet {
|
|
107
107
|
rotationSystem: RotationSystemEnum;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model, Optional } from 'sequelize';
|
|
3
3
|
import { PlayerId, TeamId, TeamModel } from '.';
|
|
4
|
-
import { ConditionLogic, CourtPosition, EnergyBand, PinchCondition,
|
|
4
|
+
import { BlockingAssignment, ConditionLogic, CourtPosition, EnergyBand, PinchCondition, RotationSystemEnum, SubBackMode, SubBand, SubMode } from '../../service';
|
|
5
5
|
export interface TacticsLineupAttributes {
|
|
6
6
|
[CourtPosition.LIBERO_ZONE]?: PlayerId;
|
|
7
7
|
[CourtPosition.LEFT_BACK]: PlayerId;
|
|
@@ -36,7 +36,7 @@ export interface OffensivePreferenceAttributes {
|
|
|
36
36
|
}
|
|
37
37
|
export interface BlockingPreferenceAttributes {
|
|
38
38
|
rotation: number;
|
|
39
|
-
targets: Record<PlayerId,
|
|
39
|
+
targets: Record<PlayerId, BlockingAssignment>;
|
|
40
40
|
}
|
|
41
41
|
export interface SystemSetAttributes {
|
|
42
42
|
rotationSystem: RotationSystemEnum;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
2
|
import { tacticsColumnsToApiDto, transformFromTactics, transformToTactics } from './tactics';
|
|
3
|
-
import { CourtPosition, EnergyBand, RoleEnum, RotationSystemEnum, Tactics } from '../../service';
|
|
3
|
+
import { CourtPosition, EnergyBand, NO_BLOCK, RoleEnum, RotationSystemEnum, Tactics } from '../../service';
|
|
4
4
|
import { makeCountry, makePlayer } from '../../service/test-helpers';
|
|
5
5
|
// Minimal TacticsModel-shaped object; cast through unknown since the transformer only reads columns.
|
|
6
6
|
function makeTactics(designatedSubs) {
|
|
@@ -214,6 +214,25 @@ describe('per-set tactics — service <-> row round-trip', () => {
|
|
|
214
214
|
const back = transformToTactics(attrs, roster);
|
|
215
215
|
expect(back.blockingPreferences[0].targets).toEqual({ [p4.id]: RoleEnum.OUTSIDE_HITTER, [p3.id]: RoleEnum.MIDDLE_BLOCKER });
|
|
216
216
|
});
|
|
217
|
+
// NO_BLOCK rides in the same targets map as a commit assignment, so the transformers copy it wholesale with no
|
|
218
|
+
// mapping code. This pins that: the sentinel must survive the row round-trip verbatim, mixed with a commit, and
|
|
219
|
+
// in the per-set overrides. If it ever gets translated or dropped, a player silently starts blocking again.
|
|
220
|
+
it('round-trips a NO_BLOCK assignment, mixed with a commit and in per-set overrides', () => {
|
|
221
|
+
const withNoBlock = Tactics.create({
|
|
222
|
+
lineup: { 4: p4, 3: p3, 2: p2, 5: p5, 6: p6, 1: p1, bench: [] },
|
|
223
|
+
liberoReplacements: [],
|
|
224
|
+
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: NO_BLOCK, [p3.id]: RoleEnum.MIDDLE_BLOCKER } }],
|
|
225
|
+
blockingPreferenceSets: [[{ rotation: 2, targets: { [p2.id]: NO_BLOCK } }]]
|
|
226
|
+
});
|
|
227
|
+
const attrs = transformFromTactics(withNoBlock, 'team-1');
|
|
228
|
+
expect(attrs.blocking_preferences).toEqual([
|
|
229
|
+
{ rotation: 1, targets: { [p4.id]: NO_BLOCK, [p3.id]: RoleEnum.MIDDLE_BLOCKER } }
|
|
230
|
+
]);
|
|
231
|
+
expect(attrs.blocking_preference_sets).toEqual([[{ rotation: 2, targets: { [p2.id]: NO_BLOCK } }]]);
|
|
232
|
+
const back = transformToTactics(attrs, roster);
|
|
233
|
+
expect(back.blockingPreferences[0].targets).toEqual({ [p4.id]: NO_BLOCK, [p3.id]: RoleEnum.MIDDLE_BLOCKER });
|
|
234
|
+
expect(back.blockingPreferenceSets?.[0][0].targets).toEqual({ [p2.id]: NO_BLOCK });
|
|
235
|
+
});
|
|
217
236
|
});
|
|
218
237
|
describe('libero injuries — service <-> row round-trip + lenient heal', () => {
|
|
219
238
|
const country = makeCountry();
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Your team has been promoted to a higher division."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Daily reward
|
|
31
|
-
"body": "Your daily
|
|
30
|
+
"title": "Daily reward ready",
|
|
31
|
+
"body": "Your daily reward is ready to claim!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Welcome to World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Tu equipo ha ascendido a una división superior."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Recompensa diaria
|
|
31
|
-
"body": "Tu recompensa
|
|
30
|
+
"title": "Recompensa diaria lista",
|
|
31
|
+
"body": "¡Tu recompensa diaria está lista para reclamar!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Te damos la bienvenida a World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Votre équipe a été promue dans une division supérieure."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Récompense quotidienne
|
|
31
|
-
"body": "Votre récompense
|
|
30
|
+
"title": "Récompense quotidienne prête",
|
|
31
|
+
"body": "Votre récompense quotidienne est prête à être récupérée !"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Bienvenue sur World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "La tua squadra è stata promossa in una divisione superiore."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Ricompensa giornaliera
|
|
31
|
-
"body": "La tua ricompensa
|
|
30
|
+
"title": "Ricompensa giornaliera pronta",
|
|
31
|
+
"body": "La tua ricompensa giornaliera è pronta da riscattare!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Benvenuto in World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Twoja drużyna awansowała do wyższej dywizji."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "
|
|
31
|
-
"body": "Twoja codzienna nagroda
|
|
30
|
+
"title": "Codzienna nagroda gotowa",
|
|
31
|
+
"body": "Twoja codzienna nagroda jest gotowa do odebrania!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Witaj w World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Seu time foi promovido para uma divisão superior."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Recompensa diária
|
|
31
|
-
"body": "Sua recompensa
|
|
30
|
+
"title": "Recompensa diária pronta",
|
|
31
|
+
"body": "Sua recompensa diária está pronta para coletar!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "Boas-vindas ao World Aces",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"body": "Takımın bir üst gruba terfi etti."
|
|
28
28
|
},
|
|
29
29
|
"dailyLogin": {
|
|
30
|
-
"title": "Günlük ödül
|
|
31
|
-
"body": "Günlük
|
|
30
|
+
"title": "Günlük ödül hazır",
|
|
31
|
+
"body": "Günlük ödülün alınmaya hazır!"
|
|
32
32
|
},
|
|
33
33
|
"welcome": {
|
|
34
34
|
"title": "World Aces'e hoş geldin",
|
|
@@ -87,7 +87,8 @@ export const NOTIFICATION_REGISTRY = {
|
|
|
87
87
|
},
|
|
88
88
|
DAILY_LOGIN: {
|
|
89
89
|
emitsPush: true,
|
|
90
|
-
|
|
90
|
+
// Fires when the reward becomes claimable (00:00 UTC), so it opens the daily-login claim view.
|
|
91
|
+
deepLink: () => '/daily-login',
|
|
91
92
|
pushTitleKey: 'dailyLogin.title',
|
|
92
93
|
pushBodyKey: 'dailyLogin.body',
|
|
93
94
|
inAppMessageKey: 'dailyLogin.body',
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { LineupFunction } from './lineup-function';
|
|
2
|
+
export declare const NO_BLOCK: "NO_BLOCK";
|
|
3
|
+
export type BlockingAssignment = LineupFunction | typeof NO_BLOCK;
|
|
2
4
|
export interface BlockingPreference {
|
|
3
5
|
readonly rotation: number;
|
|
4
|
-
readonly targets: Record<string,
|
|
6
|
+
readonly targets: Record<string, BlockingAssignment>;
|
|
5
7
|
}
|
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// A front-row player opted OUT of blocking for this rotation. They never join the wall under any circumstance:
|
|
2
|
+
// not as the lead blocker (the lane's next-nearest front-row player leads instead), not as a side blocker, and
|
|
3
|
+
// no trait can coerce them in -- MOVING_WALL's guaranteed lead hand, its beaten-read hand and its side-joiner
|
|
4
|
+
// roll are all suppressed, as is a dedicated-blocking commit. Sits in the same `targets` map as a commit
|
|
5
|
+
// assignment, so the two are mutually exclusive by construction: a player is reading, committed, or out.
|
|
6
|
+
export const NO_BLOCK = 'NO_BLOCK';
|
|
@@ -281,11 +281,11 @@ export declare const TacticsInputSchema: z.ZodObject<{
|
|
|
281
281
|
}, z.core.$strip>>>>;
|
|
282
282
|
blockingPreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
283
283
|
rotation: z.ZodNumber;
|
|
284
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum
|
|
284
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
285
285
|
}, z.core.$strip>>>;
|
|
286
286
|
blockingPreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
287
287
|
rotation: z.ZodNumber;
|
|
288
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum
|
|
288
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
289
289
|
}, z.core.$strip>>>>;
|
|
290
290
|
replaceKnockedImmediately: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
291
291
|
injuryReplacements: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { Player, RoleEnum } from '../../player';
|
|
3
|
+
import { NO_BLOCK } from '../blocking-preference';
|
|
3
4
|
import { EnergyBand } from '../energy-band';
|
|
4
5
|
import { RotationSystemEnum, setterCountFor } from '../rotation-system';
|
|
5
6
|
import { DesignatedSubSchema, SubBandSchema } from './designated-sub.z';
|
|
@@ -56,8 +57,12 @@ const offensivePreferenceSchema = z.object({
|
|
|
56
57
|
weights: z.record(z.string(), z.number().int().min(0)),
|
|
57
58
|
tempos: z.record(z.string(), tempoPreferenceSchema).optional()
|
|
58
59
|
});
|
|
59
|
-
//
|
|
60
|
-
|
|
60
|
+
// What a front-row starter can be assigned: an opposing attacking function to commit to (every RoleEnum except
|
|
61
|
+
// the libero, which never attacks), or NO_BLOCK to sit the rotation out of the block entirely.
|
|
62
|
+
const blockingFunctionSchema = z.union([
|
|
63
|
+
z.nativeEnum(RoleEnum).refine((v) => v !== RoleEnum.LIBERO, { message: 'BLOCKING_TARGET_CANNOT_BE_LIBERO' }),
|
|
64
|
+
z.literal(NO_BLOCK)
|
|
65
|
+
]);
|
|
61
66
|
// One rotation's dedicated-blocking assignments: `targets` maps my front-row starter ids to the opposing function
|
|
62
67
|
// each commits to block. Cross-field checks (keys are starters) live in the superRefine below.
|
|
63
68
|
const blockingPreferenceSchema = z.object({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
2
|
import { TacticsInputSchema } from './tactics.z';
|
|
3
|
+
import { NO_BLOCK } from '../blocking-preference';
|
|
3
4
|
import { RoleEnum } from '../../player';
|
|
4
5
|
import { makeCountry, makePlayer } from '../../test-helpers';
|
|
5
6
|
describe('TacticsInputSchema — second libero rules', () => {
|
|
@@ -278,4 +279,35 @@ describe('TacticsInputSchema — blocking preferences', () => {
|
|
|
278
279
|
}));
|
|
279
280
|
expect(res.success).toBe(true);
|
|
280
281
|
});
|
|
282
|
+
it('accepts NO_BLOCK as an assignment, alongside a commit on another starter', () => {
|
|
283
|
+
const res = TacticsInputSchema.safeParse(baseInput({
|
|
284
|
+
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: NO_BLOCK, [p3.id]: RoleEnum.MIDDLE_BLOCKER } }]
|
|
285
|
+
}));
|
|
286
|
+
expect(res.success).toBe(true);
|
|
287
|
+
if (res.success) {
|
|
288
|
+
expect(res.data.blockingPreferences[0].targets[p4.id]).toBe(NO_BLOCK);
|
|
289
|
+
expect(res.data.blockingPreferences[0].targets[p3.id]).toBe(RoleEnum.MIDDLE_BLOCKER);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
it('accepts NO_BLOCK in a per-set override', () => {
|
|
293
|
+
const res = TacticsInputSchema.safeParse(baseInput({
|
|
294
|
+
blockingPreferenceSets: [[{ rotation: 1, targets: { [p4.id]: NO_BLOCK } }], []]
|
|
295
|
+
}));
|
|
296
|
+
expect(res.success).toBe(true);
|
|
297
|
+
});
|
|
298
|
+
it('still rejects a NO_BLOCK assignment on a player who is not a starter', () => {
|
|
299
|
+
const res = TacticsInputSchema.safeParse(baseInput({
|
|
300
|
+
blockingPreferences: [{ rotation: 1, targets: { [reserve.id]: NO_BLOCK } }]
|
|
301
|
+
}));
|
|
302
|
+
expect(res.success).toBe(false);
|
|
303
|
+
if (!res.success) {
|
|
304
|
+
expect(res.error.issues.some(i => i.message === 'BLOCKING_PREFERENCE_BLOCKER_NOT_A_STARTER')).toBe(true);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
it('rejects an unknown assignment string', () => {
|
|
308
|
+
const res = TacticsInputSchema.safeParse(baseInput({
|
|
309
|
+
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: 'NO_BLOCKING' } }]
|
|
310
|
+
}));
|
|
311
|
+
expect(res.success).toBe(false);
|
|
312
|
+
});
|
|
281
313
|
});
|
|
@@ -289,11 +289,11 @@ export declare const TeamInputSchema: z.ZodObject<{
|
|
|
289
289
|
}, z.core.$strip>>>>;
|
|
290
290
|
blockingPreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
291
291
|
rotation: z.ZodNumber;
|
|
292
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum
|
|
292
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
293
293
|
}, z.core.$strip>>>;
|
|
294
294
|
blockingPreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
295
295
|
rotation: z.ZodNumber;
|
|
296
|
-
targets: z.ZodRecord<z.ZodString, z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum
|
|
296
|
+
targets: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>;
|
|
297
297
|
}, z.core.$strip>>>>;
|
|
298
298
|
replaceKnockedImmediately: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
299
299
|
injuryReplacements: z.ZodDefault<z.ZodArray<z.ZodObject<{
|