volleyballsimtypes 0.0.481 → 0.0.483

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.
Files changed (73) hide show
  1. package/dist/cjs/src/api/index.d.ts +10 -18
  2. package/dist/cjs/src/data/models/tactics.d.ts +17 -19
  3. package/dist/cjs/src/data/models/tactics.js +9 -0
  4. package/dist/cjs/src/data/transformers/match-preset-override.test.js +10 -1
  5. package/dist/cjs/src/data/transformers/rally-event.d.ts +2 -1
  6. package/dist/cjs/src/data/transformers/rally-event.js +12 -0
  7. package/dist/cjs/src/data/transformers/rally.js +2 -0
  8. package/dist/cjs/src/data/transformers/rally.test.d.ts +1 -0
  9. package/dist/cjs/src/data/transformers/rally.test.js +62 -0
  10. package/dist/cjs/src/data/transformers/tactics.js +38 -58
  11. package/dist/cjs/src/data/transformers/tactics.test.js +39 -20
  12. package/dist/cjs/src/service/team/blocking-preference.d.ts +5 -0
  13. package/dist/cjs/src/service/team/blocking-preference.js +2 -0
  14. package/dist/cjs/src/service/team/designated-sub.d.ts +2 -4
  15. package/dist/cjs/src/service/team/index.d.ts +2 -0
  16. package/dist/cjs/src/service/team/index.js +2 -0
  17. package/dist/cjs/src/service/team/libero-sub.d.ts +0 -4
  18. package/dist/cjs/src/service/team/offensive-preference.d.ts +1 -2
  19. package/dist/cjs/src/service/team/pinch-condition.d.ts +11 -3
  20. package/dist/cjs/src/service/team/pinch-condition.js +9 -4
  21. package/dist/cjs/src/service/team/schemas/designated-sub.z.d.ts +30 -32
  22. package/dist/cjs/src/service/team/schemas/designated-sub.z.js +27 -23
  23. package/dist/cjs/src/service/team/schemas/designated-sub.z.test.js +4 -2
  24. package/dist/cjs/src/service/team/schemas/libero-sub.z.d.ts +15 -34
  25. package/dist/cjs/src/service/team/schemas/libero-sub.z.js +10 -26
  26. package/dist/cjs/src/service/team/schemas/libero-sub.z.test.js +74 -35
  27. package/dist/cjs/src/service/team/schemas/tactics.z.d.ts +39 -39
  28. package/dist/cjs/src/service/team/schemas/tactics.z.js +47 -13
  29. package/dist/cjs/src/service/team/schemas/tactics.z.test.js +81 -8
  30. package/dist/cjs/src/service/team/schemas/team.z.d.ts +38 -38
  31. package/dist/cjs/src/service/team/sub-config-convert.d.ts +13 -0
  32. package/dist/cjs/src/service/team/sub-config-convert.js +91 -0
  33. package/dist/cjs/src/service/team/sub-config-convert.test.d.ts +1 -0
  34. package/dist/cjs/src/service/team/sub-config-convert.test.js +84 -0
  35. package/dist/cjs/src/service/team/tactics.d.ts +5 -0
  36. package/dist/cjs/src/service/team/tactics.js +3 -1
  37. package/dist/esm/src/api/index.d.ts +10 -18
  38. package/dist/esm/src/data/models/tactics.d.ts +17 -19
  39. package/dist/esm/src/data/models/tactics.js +9 -0
  40. package/dist/esm/src/data/transformers/match-preset-override.test.js +10 -1
  41. package/dist/esm/src/data/transformers/rally-event.d.ts +2 -1
  42. package/dist/esm/src/data/transformers/rally-event.js +12 -1
  43. package/dist/esm/src/data/transformers/rally.js +4 -2
  44. package/dist/esm/src/data/transformers/rally.test.d.ts +1 -0
  45. package/dist/esm/src/data/transformers/rally.test.js +60 -0
  46. package/dist/esm/src/data/transformers/tactics.js +39 -59
  47. package/dist/esm/src/data/transformers/tactics.test.js +40 -21
  48. package/dist/esm/src/service/team/blocking-preference.d.ts +5 -0
  49. package/dist/esm/src/service/team/blocking-preference.js +1 -0
  50. package/dist/esm/src/service/team/designated-sub.d.ts +2 -4
  51. package/dist/esm/src/service/team/index.d.ts +2 -0
  52. package/dist/esm/src/service/team/index.js +2 -0
  53. package/dist/esm/src/service/team/libero-sub.d.ts +0 -4
  54. package/dist/esm/src/service/team/offensive-preference.d.ts +1 -2
  55. package/dist/esm/src/service/team/pinch-condition.d.ts +11 -3
  56. package/dist/esm/src/service/team/pinch-condition.js +9 -4
  57. package/dist/esm/src/service/team/schemas/designated-sub.z.d.ts +30 -32
  58. package/dist/esm/src/service/team/schemas/designated-sub.z.js +26 -22
  59. package/dist/esm/src/service/team/schemas/designated-sub.z.test.js +4 -2
  60. package/dist/esm/src/service/team/schemas/libero-sub.z.d.ts +15 -34
  61. package/dist/esm/src/service/team/schemas/libero-sub.z.js +9 -25
  62. package/dist/esm/src/service/team/schemas/libero-sub.z.test.js +75 -36
  63. package/dist/esm/src/service/team/schemas/tactics.z.d.ts +39 -39
  64. package/dist/esm/src/service/team/schemas/tactics.z.js +48 -14
  65. package/dist/esm/src/service/team/schemas/tactics.z.test.js +81 -8
  66. package/dist/esm/src/service/team/schemas/team.z.d.ts +38 -38
  67. package/dist/esm/src/service/team/sub-config-convert.d.ts +13 -0
  68. package/dist/esm/src/service/team/sub-config-convert.js +85 -0
  69. package/dist/esm/src/service/team/sub-config-convert.test.d.ts +1 -0
  70. package/dist/esm/src/service/team/sub-config-convert.test.js +82 -0
  71. package/dist/esm/src/service/team/tactics.d.ts +5 -0
  72. package/dist/esm/src/service/team/tactics.js +3 -1
  73. package/package.json +1 -1
@@ -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 player_1 = require("../../player");
5
6
  const test_helpers_1 = require("../../test-helpers");
6
7
  (0, globals_1.describe)('TacticsInputSchema — second libero rules', () => {
7
8
  const country = (0, test_helpers_1.makeCountry)();
@@ -95,7 +96,7 @@ const test_helpers_1 = require("../../test-helpers");
95
96
  { rotationSystem: '4-2', designatedSetters: [p1, p4] }
96
97
  ],
97
98
  offensivePreferenceSets: [
98
- [{ rotation: 1, order: [p2, p3] }],
99
+ [{ rotation: 1, weights: { [p2.id]: 60, [p3.id]: 40 } }],
99
100
  []
100
101
  ]
101
102
  }));
@@ -104,7 +105,7 @@ const test_helpers_1 = require("../../test-helpers");
104
105
  (0, globals_1.it)('carries the per-set fields through Tactics.create parsing', () => {
105
106
  const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
106
107
  systemSets: [{ rotationSystem: '5-1', designatedSetters: [p1] }],
107
- offensivePreferenceSets: [[{ rotation: 2, order: [p3] }]]
108
+ offensivePreferenceSets: [[{ rotation: 2, weights: { [p3.id]: 100 } }]]
108
109
  }));
109
110
  (0, globals_1.expect)(res.success).toBe(true);
110
111
  if (res.success) {
@@ -153,7 +154,7 @@ const test_helpers_1 = require("../../test-helpers");
153
154
  });
154
155
  (0, globals_1.it)('rejects a per-set preferences list with a duplicate rotation', () => {
155
156
  const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
156
- offensivePreferenceSets: [[{ rotation: 1, order: [p2] }, { rotation: 1, order: [p3] }]]
157
+ offensivePreferenceSets: [[{ rotation: 1, weights: { [p2.id]: 100 } }, { rotation: 1, weights: { [p3.id]: 100 } }]]
157
158
  }));
158
159
  (0, globals_1.expect)(res.success).toBe(false);
159
160
  if (!res.success) {
@@ -161,18 +162,27 @@ const test_helpers_1 = require("../../test-helpers");
161
162
  (0, globals_1.expect)(issue?.path).toEqual(['offensivePreferenceSets', 0]);
162
163
  }
163
164
  });
164
- (0, globals_1.it)('rejects a per-set preferences order that lists a non-starter', () => {
165
+ (0, globals_1.it)('rejects a per-set preferences map that keys a non-starter', () => {
165
166
  const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
166
- offensivePreferenceSets: [[{ rotation: 1, order: [reserve] }]]
167
+ offensivePreferenceSets: [[{ rotation: 1, weights: { [reserve.id]: 100 } }]]
167
168
  }));
168
169
  (0, globals_1.expect)(res.success).toBe(false);
169
170
  if (!res.success) {
170
171
  (0, globals_1.expect)(res.error.issues.some(i => i.message === 'OFFENSIVE_PREFERENCE_ATTACKER_NOT_A_STARTER')).toBe(true);
171
172
  }
172
173
  });
174
+ (0, globals_1.it)('rejects offensive preference weights that do not sum to 100', () => {
175
+ const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
176
+ offensivePreferences: [{ rotation: 1, weights: { [p2.id]: 50, [p3.id]: 40 } }]
177
+ }));
178
+ (0, globals_1.expect)(res.success).toBe(false);
179
+ if (!res.success) {
180
+ (0, globals_1.expect)(res.error.issues.some(i => i.message === 'OFFENSIVE_PREFERENCE_WEIGHTS_MUST_SUM_TO_100')).toBe(true);
181
+ }
182
+ });
173
183
  (0, globals_1.it)('accepts offensive preferences with a starter-keyed tempos map', () => {
174
184
  const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
175
- offensivePreferences: [{ rotation: 1, order: [p2, p3], tempos: { [p2.id]: 'FAST', [p3.id]: 'HIGH' } }]
185
+ offensivePreferences: [{ rotation: 1, weights: { [p2.id]: 60, [p3.id]: 40 }, tempos: { [p2.id]: 'FAST', [p3.id]: 'HIGH' } }]
176
186
  }));
177
187
  (0, globals_1.expect)(res.success).toBe(true);
178
188
  if (res.success) {
@@ -181,7 +191,7 @@ const test_helpers_1 = require("../../test-helpers");
181
191
  });
182
192
  (0, globals_1.it)('rejects a tempos map keyed by a non-starter', () => {
183
193
  const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
184
- offensivePreferences: [{ rotation: 1, order: [p2], tempos: { [reserve.id]: 'FAST' } }]
194
+ offensivePreferences: [{ rotation: 1, weights: { [p2.id]: 100 }, tempos: { [reserve.id]: 'FAST' } }]
185
195
  }));
186
196
  (0, globals_1.expect)(res.success).toBe(false);
187
197
  if (!res.success) {
@@ -190,7 +200,7 @@ const test_helpers_1 = require("../../test-helpers");
190
200
  });
191
201
  (0, globals_1.it)('rejects an invalid tempo value', () => {
192
202
  const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
193
- offensivePreferences: [{ rotation: 1, order: [p2], tempos: { [p2.id]: 'SLOW' } }]
203
+ offensivePreferences: [{ rotation: 1, weights: { [p2.id]: 100 }, tempos: { [p2.id]: 'SLOW' } }]
194
204
  }));
195
205
  (0, globals_1.expect)(res.success).toBe(false);
196
206
  });
@@ -208,3 +218,66 @@ const test_helpers_1 = require("../../test-helpers");
208
218
  }
209
219
  });
210
220
  });
221
+ (0, globals_1.describe)('TacticsInputSchema — blocking preferences', () => {
222
+ const country = (0, test_helpers_1.makeCountry)();
223
+ const p1 = (0, test_helpers_1.makePlayer)(country);
224
+ const p2 = (0, test_helpers_1.makePlayer)(country);
225
+ const p3 = (0, test_helpers_1.makePlayer)(country);
226
+ const p4 = (0, test_helpers_1.makePlayer)(country);
227
+ const p5 = (0, test_helpers_1.makePlayer)(country);
228
+ const p6 = (0, test_helpers_1.makePlayer)(country);
229
+ const reserve = (0, test_helpers_1.makePlayer)(country);
230
+ // Front-row starters (zones 2/3/4) are p2, p3, p4; the validator only requires target keys to be starters.
231
+ function baseInput(overrides = {}) {
232
+ return {
233
+ lineup: { 4: p4, 3: p3, 2: p2, 5: p5, 6: p6, 1: p1, bench: [] },
234
+ liberoReplacements: [],
235
+ ...overrides
236
+ };
237
+ }
238
+ (0, globals_1.it)('accepts a blocking preference that keys starters to attacking functions', () => {
239
+ const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
240
+ blockingPreferences: [{ rotation: 1, targets: { [p4.id]: player_1.RoleEnum.OUTSIDE_HITTER, [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } }]
241
+ }));
242
+ (0, globals_1.expect)(res.success).toBe(true);
243
+ if (res.success) {
244
+ (0, globals_1.expect)(res.data.blockingPreferences[0].targets[p4.id]).toBe(player_1.RoleEnum.OUTSIDE_HITTER);
245
+ }
246
+ });
247
+ (0, globals_1.it)('rejects a blocking target that is not a starter', () => {
248
+ const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
249
+ blockingPreferences: [{ rotation: 1, targets: { [reserve.id]: player_1.RoleEnum.OUTSIDE_HITTER } }]
250
+ }));
251
+ (0, globals_1.expect)(res.success).toBe(false);
252
+ if (!res.success) {
253
+ (0, globals_1.expect)(res.error.issues.some(i => i.message === 'BLOCKING_PREFERENCE_BLOCKER_NOT_A_STARTER')).toBe(true);
254
+ }
255
+ });
256
+ (0, globals_1.it)('rejects a blocking target function of libero', () => {
257
+ const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
258
+ blockingPreferences: [{ rotation: 1, targets: { [p4.id]: player_1.RoleEnum.LIBERO } }]
259
+ }));
260
+ (0, globals_1.expect)(res.success).toBe(false);
261
+ if (!res.success) {
262
+ (0, globals_1.expect)(res.error.issues.some(i => i.message === 'BLOCKING_TARGET_CANNOT_BE_LIBERO')).toBe(true);
263
+ }
264
+ });
265
+ (0, globals_1.it)('rejects a duplicate rotation in blocking preferences', () => {
266
+ const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
267
+ blockingPreferences: [
268
+ { rotation: 1, targets: { [p4.id]: player_1.RoleEnum.OUTSIDE_HITTER } },
269
+ { rotation: 1, targets: { [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } }
270
+ ]
271
+ }));
272
+ (0, globals_1.expect)(res.success).toBe(false);
273
+ if (!res.success) {
274
+ (0, globals_1.expect)(res.error.issues.some(i => i.message === 'BLOCKING_PREFERENCE_DUPLICATE_ROTATION')).toBe(true);
275
+ }
276
+ });
277
+ (0, globals_1.it)('accepts per-set blocking preference overrides', () => {
278
+ const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
279
+ blockingPreferenceSets: [[{ rotation: 1, targets: { [p4.id]: player_1.RoleEnum.OPPOSITE_HITTER } }], []]
280
+ }));
281
+ (0, globals_1.expect)(res.success).toBe(true);
282
+ });
283
+ });
@@ -23,16 +23,9 @@ export declare const TeamInputSchema: z.ZodObject<{
23
23
  }, z.core.$strip>;
24
24
  liberoReplacements: z.ZodArray<z.ZodCustom<Player, Player>>;
25
25
  receiveRotationOffset: z.ZodDefault<z.ZodBoolean>;
26
- designatedSubs: z.ZodDefault<z.ZodArray<z.ZodObject<{
27
- sets: z.ZodOptional<z.ZodArray<z.ZodObject<{
28
- mode: z.ZodEnum<{
29
- NEVER: "NEVER";
30
- FATIGUE: "FATIGUE";
31
- PINCH: "PINCH";
32
- }>;
26
+ designatedSubs: z.ZodDefault<z.ZodArray<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
27
+ sets: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
33
28
  bench: z.ZodOptional<z.ZodCustom<Player, Player>>;
34
- fatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
35
- benchFatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
36
29
  conditions: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
37
30
  type: z.ZodLiteral<import("..").PinchConditionType.ASAP>;
38
31
  }, z.core.$strip>, z.ZodObject<{
@@ -64,9 +57,13 @@ export declare const TeamInputSchema: z.ZodObject<{
64
57
  }, z.core.$strip>, z.ZodObject<{
65
58
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
66
59
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
60
+ }, z.core.$strip>, z.ZodObject<{
61
+ type: z.ZodLiteral<import("..").PinchConditionType.FATIGUE>;
62
+ band: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
67
63
  }, z.core.$strip>], "type">>>;
68
64
  conditionLogic: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"ALL">, z.ZodLiteral<"ANY">]>>;
69
65
  pinchServer: z.ZodOptional<z.ZodBoolean>;
66
+ benchFatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
70
67
  subBackMode: z.ZodOptional<z.ZodEnum<{
71
68
  FATIGUE: "FATIGUE";
72
69
  CONDITIONS: "CONDITIONS";
@@ -102,17 +99,13 @@ export declare const TeamInputSchema: z.ZodObject<{
102
99
  }, z.core.$strip>, z.ZodObject<{
103
100
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
104
101
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
102
+ }, z.core.$strip>, z.ZodObject<{
103
+ type: z.ZodLiteral<import("..").PinchConditionType.FATIGUE>;
104
+ band: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
105
105
  }, z.core.$strip>], "type">>>;
106
106
  subBackConditionLogic: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"ALL">, z.ZodLiteral<"ANY">]>>;
107
- }, z.core.$strip>>>;
108
- mode: z.ZodEnum<{
109
- NEVER: "NEVER";
110
- FATIGUE: "FATIGUE";
111
- PINCH: "PINCH";
112
- }>;
107
+ }, z.core.$strip>>>>;
113
108
  bench: z.ZodOptional<z.ZodCustom<Player, Player>>;
114
- fatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
115
- benchFatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
116
109
  conditions: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
117
110
  type: z.ZodLiteral<import("..").PinchConditionType.ASAP>;
118
111
  }, z.core.$strip>, z.ZodObject<{
@@ -144,9 +137,13 @@ export declare const TeamInputSchema: z.ZodObject<{
144
137
  }, z.core.$strip>, z.ZodObject<{
145
138
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
146
139
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
140
+ }, z.core.$strip>, z.ZodObject<{
141
+ type: z.ZodLiteral<import("..").PinchConditionType.FATIGUE>;
142
+ band: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
147
143
  }, z.core.$strip>], "type">>>;
148
144
  conditionLogic: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"ALL">, z.ZodLiteral<"ANY">]>>;
149
145
  pinchServer: z.ZodOptional<z.ZodBoolean>;
146
+ benchFatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
150
147
  subBackMode: z.ZodOptional<z.ZodEnum<{
151
148
  FATIGUE: "FATIGUE";
152
149
  CONDITIONS: "CONDITIONS";
@@ -182,21 +179,17 @@ export declare const TeamInputSchema: z.ZodObject<{
182
179
  }, z.core.$strip>, z.ZodObject<{
183
180
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
184
181
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
182
+ }, z.core.$strip>, z.ZodObject<{
183
+ type: z.ZodLiteral<import("..").PinchConditionType.FATIGUE>;
184
+ band: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
185
185
  }, z.core.$strip>], "type">>>;
186
186
  subBackConditionLogic: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"ALL">, z.ZodLiteral<"ANY">]>>;
187
187
  starter: z.ZodCustom<Player, Player>;
188
- }, z.core.$strip>>>;
188
+ }, z.core.$strip>>>>;
189
189
  substitutionBand: z.ZodDefault<z.ZodUnion<readonly [z.ZodEnum<typeof import("..").EnergyBand>, z.ZodLiteral<"NEVER">]>>;
190
190
  secondLibero: z.ZodOptional<z.ZodCustom<Player, Player>>;
191
- liberoSub: z.ZodOptional<z.ZodObject<{
192
- sets: z.ZodOptional<z.ZodArray<z.ZodObject<{
193
- mode: z.ZodEnum<{
194
- NEVER: "NEVER";
195
- FATIGUE: "FATIGUE";
196
- CONDITIONS: "CONDITIONS";
197
- ALWAYS: "ALWAYS";
198
- }>;
199
- fatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
191
+ liberoSub: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
192
+ sets: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
200
193
  conditions: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
201
194
  type: z.ZodLiteral<import("..").PinchConditionType.ASAP>;
202
195
  }, z.core.$strip>, z.ZodObject<{
@@ -228,16 +221,12 @@ export declare const TeamInputSchema: z.ZodObject<{
228
221
  }, z.core.$strip>, z.ZodObject<{
229
222
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
230
223
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
224
+ }, z.core.$strip>, z.ZodObject<{
225
+ type: z.ZodLiteral<import("..").PinchConditionType.FATIGUE>;
226
+ band: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
231
227
  }, z.core.$strip>], "type">>>;
232
228
  conditionLogic: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"ALL">, z.ZodLiteral<"ANY">]>>;
233
- }, z.core.$strip>>>;
234
- mode: z.ZodEnum<{
235
- NEVER: "NEVER";
236
- FATIGUE: "FATIGUE";
237
- CONDITIONS: "CONDITIONS";
238
- ALWAYS: "ALWAYS";
239
- }>;
240
- fatigueBand: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
229
+ }, z.core.$strip>>>>;
241
230
  conditions: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
242
231
  type: z.ZodLiteral<import("..").PinchConditionType.ASAP>;
243
232
  }, z.core.$strip>, z.ZodObject<{
@@ -269,15 +258,18 @@ export declare const TeamInputSchema: z.ZodObject<{
269
258
  }, z.core.$strip>, z.ZodObject<{
270
259
  type: z.ZodLiteral<import("..").PinchConditionType.PHASE>;
271
260
  phase: z.ZodEnum<typeof import("..").MatchPhase>;
261
+ }, z.core.$strip>, z.ZodObject<{
262
+ type: z.ZodLiteral<import("..").PinchConditionType.FATIGUE>;
263
+ band: z.ZodOptional<z.ZodEnum<typeof import("..").EnergyBand>>;
272
264
  }, z.core.$strip>], "type">>>;
273
265
  conditionLogic: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"ALL">, z.ZodLiteral<"ANY">]>>;
274
- }, z.core.$strip>>;
266
+ }, z.core.$strip>>>;
275
267
  liberoReplacementSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodCustom<Player, Player>>>>;
276
268
  rotationSystem: z.ZodDefault<z.ZodEnum<typeof import("..").RotationSystemEnum>>;
277
269
  designatedSetters: z.ZodDefault<z.ZodArray<z.ZodCustom<Player, Player>>>;
278
270
  offensivePreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
279
271
  rotation: z.ZodNumber;
280
- order: z.ZodArray<z.ZodCustom<Player, Player>>;
272
+ weights: z.ZodRecord<z.ZodString, z.ZodNumber>;
281
273
  tempos: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
282
274
  FAST: "FAST";
283
275
  HIGH: "HIGH";
@@ -289,12 +281,20 @@ export declare const TeamInputSchema: z.ZodObject<{
289
281
  }, z.core.$strip>>>;
290
282
  offensivePreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
291
283
  rotation: z.ZodNumber;
292
- order: z.ZodArray<z.ZodCustom<Player, Player>>;
284
+ weights: z.ZodRecord<z.ZodString, z.ZodNumber>;
293
285
  tempos: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
294
286
  FAST: "FAST";
295
287
  HIGH: "HIGH";
296
288
  }>>>;
297
289
  }, z.core.$strip>>>>;
290
+ blockingPreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
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>>>;
293
+ }, z.core.$strip>>>;
294
+ blockingPreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
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>>>;
297
+ }, z.core.$strip>>>>;
298
298
  replaceKnockedImmediately: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
299
299
  injuryReplacements: z.ZodDefault<z.ZodArray<z.ZodObject<{
300
300
  starter: z.ZodCustom<Player, Player>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Convert ONE legacy set-sub config (flat or per-set entry). Handles BOTH legacy generations:
3
+ * mode-era rows ({mode: NEVER|FATIGUE|PINCH}) and the oldest isPinchServer-era rows (no mode;
4
+ * isPinchServer flag + a 'NEVER' fatigueBand for the old never-sub state). Non-records and
5
+ * already-unified shapes (neither mode nor isPinchServer nor fatigueBand keys) pass through.
6
+ */
7
+ export declare function convertLegacySetSubConfig(raw: unknown): unknown;
8
+ /** Convert a legacy DesignatedSub (flat fields + per-set entries); unified shapes pass through. */
9
+ export declare function convertLegacyDesignatedSub(raw: unknown): unknown;
10
+ /** Convert ONE legacy libero set-sub config; unified shapes pass through. */
11
+ export declare function convertLegacyLiberoSetSubConfig(raw: unknown): unknown;
12
+ /** Convert a legacy LiberoSubConfig (flat fields + per-set entries); unified shapes pass through. */
13
+ export declare function convertLegacyLiberoSubConfig(raw: unknown): unknown;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertLegacySetSubConfig = convertLegacySetSubConfig;
4
+ exports.convertLegacyDesignatedSub = convertLegacyDesignatedSub;
5
+ exports.convertLegacyLiberoSetSubConfig = convertLegacyLiberoSetSubConfig;
6
+ exports.convertLegacyLiberoSubConfig = convertLegacyLiberoSubConfig;
7
+ const energy_band_1 = require("./energy-band");
8
+ const pinch_condition_1 = require("./pinch-condition");
9
+ function isRecord(v) {
10
+ return typeof v === 'object' && v != null && !Array.isArray(v);
11
+ }
12
+ function fatigueCondition(band) {
13
+ return Object.values(energy_band_1.EnergyBand).includes(band)
14
+ ? { type: pinch_condition_1.PinchConditionType.FATIGUE, band }
15
+ : { type: pinch_condition_1.PinchConditionType.FATIGUE };
16
+ }
17
+ /**
18
+ * Convert ONE legacy set-sub config (flat or per-set entry). Handles BOTH legacy generations:
19
+ * mode-era rows ({mode: NEVER|FATIGUE|PINCH}) and the oldest isPinchServer-era rows (no mode;
20
+ * isPinchServer flag + a 'NEVER' fatigueBand for the old never-sub state). Non-records and
21
+ * already-unified shapes (neither mode nor isPinchServer nor fatigueBand keys) pass through.
22
+ */
23
+ function convertLegacySetSubConfig(raw) {
24
+ if (!isRecord(raw))
25
+ return raw;
26
+ // Derive the mode for the oldest (pre-mode) generation; a unified shape has none of these keys.
27
+ const mode = raw.mode ?? (raw.isPinchServer === true
28
+ ? 'PINCH'
29
+ : raw.fatigueBand === 'NEVER'
30
+ ? 'NEVER'
31
+ : raw.fatigueBand != null || 'isPinchServer' in raw ? 'FATIGUE' : null);
32
+ if (mode == null)
33
+ return raw;
34
+ const { mode: _m, fatigueBand, isPinchServer: _p, ...rest } = raw;
35
+ if (mode === 'NEVER') {
36
+ // Old NEVER dropped every other field; an explicit empty condition list = never substituted.
37
+ return { conditions: [] };
38
+ }
39
+ if (mode === 'FATIGUE') {
40
+ return {
41
+ ...rest,
42
+ conditions: [fatigueCondition(fatigueBand)],
43
+ conditionLogic: 'ALL',
44
+ pinchServer: false,
45
+ subBackMode: rest.subBackMode ?? 'FATIGUE'
46
+ };
47
+ }
48
+ if (mode === 'PINCH') {
49
+ // A legacy PINCH row without the flag is a serve-and-return pinch server (the documented default).
50
+ return { ...rest, pinchServer: rest.pinchServer ?? true };
51
+ }
52
+ // Unknown legacy mode: strip it and let validation judge the rest.
53
+ return rest;
54
+ }
55
+ /** Convert a legacy DesignatedSub (flat fields + per-set entries); unified shapes pass through. */
56
+ function convertLegacyDesignatedSub(raw) {
57
+ if (!isRecord(raw))
58
+ return raw;
59
+ const { starter, sets, ...cfg } = raw;
60
+ const flat = convertLegacySetSubConfig(cfg);
61
+ const out = { ...(isRecord(flat) ? flat : {}), starter };
62
+ if (Array.isArray(sets))
63
+ out.sets = sets.map(convertLegacySetSubConfig);
64
+ return out;
65
+ }
66
+ /** Convert ONE legacy libero set-sub config; unified shapes pass through. */
67
+ function convertLegacyLiberoSetSubConfig(raw) {
68
+ if (!isRecord(raw) || raw.mode == null)
69
+ return raw;
70
+ const { mode, fatigueBand, ...rest } = raw;
71
+ if (mode === 'NEVER')
72
+ return { conditions: [] };
73
+ if (mode === 'ALWAYS')
74
+ return { ...rest, conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }], conditionLogic: 'ALL' };
75
+ if (mode === 'FATIGUE')
76
+ return { ...rest, conditions: [fatigueCondition(fatigueBand)], conditionLogic: 'ALL' };
77
+ if (mode === 'CONDITIONS')
78
+ return rest;
79
+ return rest;
80
+ }
81
+ /** Convert a legacy LiberoSubConfig (flat fields + per-set entries); unified shapes pass through. */
82
+ function convertLegacyLiberoSubConfig(raw) {
83
+ if (!isRecord(raw))
84
+ return raw;
85
+ const { sets, ...cfg } = raw;
86
+ const flat = convertLegacyLiberoSetSubConfig(cfg);
87
+ const out = { ...(isRecord(flat) ? flat : {}) };
88
+ if (Array.isArray(sets))
89
+ out.sets = sets.map(convertLegacyLiberoSetSubConfig);
90
+ return out;
91
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const globals_1 = require("@jest/globals");
4
+ const energy_band_1 = require("./energy-band");
5
+ const pinch_condition_1 = require("./pinch-condition");
6
+ const sub_config_convert_1 = require("./sub-config-convert");
7
+ // The conversion matrix for the unified condition engine: every legacy generation must land on the exact
8
+ // unified shape (these functions are the single conversion authority used by the schema preprocess, the
9
+ // transformers, and the API repo's read path).
10
+ (0, globals_1.describe)('convertLegacySetSubConfig', () => {
11
+ (0, globals_1.it)('passes an already-unified config through untouched', () => {
12
+ const unified = { bench: 'X', conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }], pinchServer: true };
13
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacySetSubConfig)(unified)).toBe(unified);
14
+ });
15
+ (0, globals_1.it)('converts mode NEVER to an explicit empty condition list, dropping every other field', () => {
16
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacySetSubConfig)({ mode: 'NEVER', bench: 'X' })).toEqual({ conditions: [] });
17
+ });
18
+ (0, globals_1.it)('converts mode FATIGUE with a band to a FATIGUE condition + FATIGUE sub-back', () => {
19
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacySetSubConfig)({ mode: 'FATIGUE', fatigueBand: energy_band_1.EnergyBand.WORN, bench: 'X', benchFatigueBand: energy_band_1.EnergyBand.TIRED })).toEqual({
20
+ bench: 'X',
21
+ benchFatigueBand: energy_band_1.EnergyBand.TIRED,
22
+ conditions: [{ type: pinch_condition_1.PinchConditionType.FATIGUE, band: energy_band_1.EnergyBand.WORN }],
23
+ conditionLogic: 'ALL',
24
+ pinchServer: false,
25
+ subBackMode: 'FATIGUE'
26
+ });
27
+ });
28
+ (0, globals_1.it)('converts mode FATIGUE without a band to a bandless FATIGUE condition (team default)', () => {
29
+ const out = (0, sub_config_convert_1.convertLegacySetSubConfig)({ mode: 'FATIGUE' });
30
+ (0, globals_1.expect)(out.conditions).toEqual([{ type: pinch_condition_1.PinchConditionType.FATIGUE }]);
31
+ });
32
+ (0, globals_1.it)('converts mode PINCH keeping conditions and defaulting a missing pinchServer flag to true', () => {
33
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacySetSubConfig)({ mode: 'PINCH', bench: 'X', conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }] })).toEqual({
34
+ bench: 'X',
35
+ conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }],
36
+ pinchServer: true
37
+ });
38
+ });
39
+ (0, globals_1.it)('keeps an explicit pinchServer false on a legacy PINCH regular conditional sub', () => {
40
+ const out = (0, sub_config_convert_1.convertLegacySetSubConfig)({ mode: 'PINCH', bench: 'X', conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }], pinchServer: false, subBackMode: 'CONDITIONS', subBackConditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }] });
41
+ (0, globals_1.expect)(out.pinchServer).toBe(false);
42
+ (0, globals_1.expect)(out.subBackMode).toBe('CONDITIONS');
43
+ });
44
+ (0, globals_1.it)('converts the oldest isPinchServer-era row to a pinch server', () => {
45
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacySetSubConfig)({ isPinchServer: true, bench: 'X', conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }] })).toEqual({
46
+ bench: 'X',
47
+ conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }],
48
+ pinchServer: true
49
+ });
50
+ });
51
+ (0, globals_1.it)("converts the oldest 'NEVER' fatigueBand row to never (empty conditions)", () => {
52
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacySetSubConfig)({ fatigueBand: 'NEVER' })).toEqual({ conditions: [] });
53
+ });
54
+ (0, globals_1.it)('converts the oldest band-only row to a FATIGUE condition', () => {
55
+ const out = (0, sub_config_convert_1.convertLegacySetSubConfig)({ fatigueBand: energy_band_1.EnergyBand.EXHAUSTED });
56
+ (0, globals_1.expect)(out.conditions).toEqual([{ type: pinch_condition_1.PinchConditionType.FATIGUE, band: energy_band_1.EnergyBand.EXHAUSTED }]);
57
+ });
58
+ (0, globals_1.it)('strips an unknown legacy mode and keeps the rest (lenient heal)', () => {
59
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacySetSubConfig)({ mode: 'SOMETIMES', bench: 'X' })).toEqual({ bench: 'X' });
60
+ });
61
+ });
62
+ (0, globals_1.describe)('convertLegacyDesignatedSub', () => {
63
+ (0, globals_1.it)('converts the flat fields and every per-set entry, keeping the starter', () => {
64
+ const out = (0, sub_config_convert_1.convertLegacyDesignatedSub)({
65
+ starter: 'S',
66
+ mode: 'FATIGUE',
67
+ fatigueBand: energy_band_1.EnergyBand.TIRED,
68
+ sets: [{ mode: 'NEVER' }, { mode: 'PINCH', bench: 'X', conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }] }]
69
+ });
70
+ (0, globals_1.expect)(out.starter).toBe('S');
71
+ (0, globals_1.expect)(out.conditions).toEqual([{ type: pinch_condition_1.PinchConditionType.FATIGUE, band: energy_band_1.EnergyBand.TIRED }]);
72
+ (0, globals_1.expect)(out.sets[0]).toEqual({ conditions: [] });
73
+ (0, globals_1.expect)(out.sets[1].pinchServer).toBe(true);
74
+ });
75
+ });
76
+ (0, globals_1.describe)('convertLegacyLiberoSetSubConfig', () => {
77
+ (0, globals_1.it)('maps each legacy libero mode to its unified condition list', () => {
78
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacyLiberoSetSubConfig)({ mode: 'NEVER' })).toEqual({ conditions: [] });
79
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacyLiberoSetSubConfig)({ mode: 'ALWAYS' })).toEqual({ conditions: [{ type: pinch_condition_1.PinchConditionType.ASAP }], conditionLogic: 'ALL' });
80
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacyLiberoSetSubConfig)({ mode: 'FATIGUE', fatigueBand: energy_band_1.EnergyBand.WORN })).toEqual({ conditions: [{ type: pinch_condition_1.PinchConditionType.FATIGUE, band: energy_band_1.EnergyBand.WORN }], conditionLogic: 'ALL' });
81
+ const conditions = [{ type: pinch_condition_1.PinchConditionType.PHASE, phase: 'RECEIVING' }];
82
+ (0, globals_1.expect)((0, sub_config_convert_1.convertLegacyLiberoSetSubConfig)({ mode: 'CONDITIONS', conditions, conditionLogic: 'ANY' })).toEqual({ conditions, conditionLogic: 'ANY' });
83
+ });
84
+ });
@@ -5,6 +5,7 @@ import { LiberoSubConfig } from './libero-sub';
5
5
  import { SubBand } from './energy-band';
6
6
  import { RotationSystemEnum } from './rotation-system';
7
7
  import { OffensivePreference } from './offensive-preference';
8
+ import { BlockingPreference } from './blocking-preference';
8
9
  import { InjuryReplacement } from './injury-replacement';
9
10
  import { LiberoInjuryConfig } from './libero-injury';
10
11
  export interface StartingLineup {
@@ -38,6 +39,8 @@ export interface TacticsOpts {
38
39
  readonly replaceKnockedImmediately: Record<string, boolean>;
39
40
  readonly injuryReplacements: InjuryReplacement[];
40
41
  readonly liberoInjury?: LiberoInjuryConfig;
42
+ readonly blockingPreferences: BlockingPreference[];
43
+ readonly blockingPreferenceSets?: BlockingPreference[][];
41
44
  }
42
45
  export declare class Tactics {
43
46
  readonly lineup: StartingLineup;
@@ -56,6 +59,8 @@ export declare class Tactics {
56
59
  readonly replaceKnockedImmediately: Record<string, boolean>;
57
60
  readonly injuryReplacements: InjuryReplacement[];
58
61
  readonly liberoInjury?: LiberoInjuryConfig;
62
+ readonly blockingPreferences: BlockingPreference[];
63
+ readonly blockingPreferenceSets?: BlockingPreference[][];
59
64
  static create(input: unknown): Tactics;
60
65
  private constructor();
61
66
  findPlayerInLineup(id: string): CourtPosition | undefined;
@@ -18,7 +18,7 @@ class Tactics {
18
18
  }
19
19
  return new Tactics(result.data);
20
20
  }
21
- constructor({ lineup, liberoReplacements, receiveRotationOffset = false, designatedSubs = [], substitutionBand = energy_band_1.EnergyBand.TIRED, secondLibero, liberoSub, liberoReplacementSets, rotationSystem = rotation_system_1.RotationSystemEnum.SIX_ZERO, designatedSetters = [], offensivePreferences = [], systemSets, offensivePreferenceSets, replaceKnockedImmediately = {}, injuryReplacements = [], liberoInjury }) {
21
+ constructor({ lineup, liberoReplacements, receiveRotationOffset = false, designatedSubs = [], substitutionBand = energy_band_1.EnergyBand.TIRED, secondLibero, liberoSub, liberoReplacementSets, rotationSystem = rotation_system_1.RotationSystemEnum.SIX_ZERO, designatedSetters = [], offensivePreferences = [], systemSets, offensivePreferenceSets, replaceKnockedImmediately = {}, injuryReplacements = [], liberoInjury, blockingPreferences = [], blockingPreferenceSets }) {
22
22
  this.lineup = lineup;
23
23
  this.liberoReplacements = liberoReplacements;
24
24
  this.receiveRotationOffset = receiveRotationOffset;
@@ -35,6 +35,8 @@ class Tactics {
35
35
  this.replaceKnockedImmediately = replaceKnockedImmediately;
36
36
  this.injuryReplacements = injuryReplacements;
37
37
  this.liberoInjury = liberoInjury;
38
+ this.blockingPreferences = blockingPreferences;
39
+ this.blockingPreferenceSets = blockingPreferenceSets;
38
40
  }
39
41
  findPlayerInLineup(id) {
40
42
  if (this.lineup.bench.some(p => p.id === id))
@@ -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, LiberoSubMode, MatchForfeitType, PerformanceStats, PinchCondition, RotationSystemEnum, SubBackMode, SubBand, SubMode } from '../service';
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, RoleEnum, RotationSystemEnum, SubBackMode, SubBand } from '../service';
2
2
  export type Rally = DataProps<_Rally> & {
3
3
  homePlayerPosition: PlayerPosition[];
4
4
  awayPlayerPosition: PlayerPosition[];
@@ -81,36 +81,28 @@ export interface StartingLineup {
81
81
  bench: string[];
82
82
  }
83
83
  export interface ApiSetSubConfig {
84
- mode: SubMode;
85
84
  benchId?: string;
86
- fatigueBand?: EnergyBand;
87
- benchFatigueBand?: EnergyBand;
88
85
  conditions?: PinchCondition[];
89
86
  conditionLogic?: ConditionLogic;
90
87
  pinchServer?: boolean;
88
+ benchFatigueBand?: EnergyBand;
91
89
  subBackMode?: SubBackMode;
92
90
  subBackConditions?: PinchCondition[];
93
91
  subBackConditionLogic?: ConditionLogic;
94
92
  }
95
- export interface ApiDesignatedSub {
93
+ export interface ApiDesignatedSub extends ApiSetSubConfig {
96
94
  starterId: string;
97
- benchId?: string;
98
- mode: SubMode;
99
- fatigueBand?: EnergyBand;
100
- benchFatigueBand?: EnergyBand;
101
- conditions?: PinchCondition[];
102
- conditionLogic?: ConditionLogic;
103
- pinchServer?: boolean;
104
- subBackMode?: SubBackMode;
105
- subBackConditions?: PinchCondition[];
106
- subBackConditionLogic?: ConditionLogic;
107
95
  sets?: ApiSetSubConfig[];
108
96
  }
109
97
  export interface ApiOffensivePreference {
110
98
  rotation: number;
111
- order: string[];
99
+ weights: Record<string, number>;
112
100
  tempos?: Record<string, 'FAST' | 'HIGH'>;
113
101
  }
102
+ export interface ApiBlockingPreference {
103
+ rotation: number;
104
+ targets: Record<string, RoleEnum>;
105
+ }
114
106
  export interface ApiSystemSet {
115
107
  rotationSystem: RotationSystemEnum;
116
108
  designatedSetters: string[];
@@ -126,8 +118,6 @@ export interface ApiLiberoInjury {
126
118
  inMatchDesignateId?: string;
127
119
  }
128
120
  export interface ApiLiberoSetSubConfig {
129
- mode: LiberoSubMode;
130
- fatigueBand?: EnergyBand;
131
121
  conditions?: PinchCondition[];
132
122
  conditionLogic?: ConditionLogic;
133
123
  }
@@ -148,6 +138,8 @@ export interface Tactics {
148
138
  offensivePreferences: ApiOffensivePreference[];
149
139
  systemSets?: ApiSystemSet[];
150
140
  offensivePreferenceSets?: ApiOffensivePreference[][];
141
+ blockingPreferences: ApiBlockingPreference[];
142
+ blockingPreferenceSets?: ApiBlockingPreference[][];
151
143
  replaceKnockedImmediately?: Record<string, boolean>;
152
144
  injuryReplacements?: ApiInjuryReplacement[];
153
145
  liberoInjury?: ApiLiberoInjury;