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
@@ -0,0 +1,85 @@
1
+ import { EnergyBand } from './energy-band';
2
+ import { PinchConditionType } from './pinch-condition';
3
+ function isRecord(v) {
4
+ return typeof v === 'object' && v != null && !Array.isArray(v);
5
+ }
6
+ function fatigueCondition(band) {
7
+ return Object.values(EnergyBand).includes(band)
8
+ ? { type: PinchConditionType.FATIGUE, band }
9
+ : { type: PinchConditionType.FATIGUE };
10
+ }
11
+ /**
12
+ * Convert ONE legacy set-sub config (flat or per-set entry). Handles BOTH legacy generations:
13
+ * mode-era rows ({mode: NEVER|FATIGUE|PINCH}) and the oldest isPinchServer-era rows (no mode;
14
+ * isPinchServer flag + a 'NEVER' fatigueBand for the old never-sub state). Non-records and
15
+ * already-unified shapes (neither mode nor isPinchServer nor fatigueBand keys) pass through.
16
+ */
17
+ export function convertLegacySetSubConfig(raw) {
18
+ if (!isRecord(raw))
19
+ return raw;
20
+ // Derive the mode for the oldest (pre-mode) generation; a unified shape has none of these keys.
21
+ const mode = raw.mode ?? (raw.isPinchServer === true
22
+ ? 'PINCH'
23
+ : raw.fatigueBand === 'NEVER'
24
+ ? 'NEVER'
25
+ : raw.fatigueBand != null || 'isPinchServer' in raw ? 'FATIGUE' : null);
26
+ if (mode == null)
27
+ return raw;
28
+ const { mode: _m, fatigueBand, isPinchServer: _p, ...rest } = raw;
29
+ if (mode === 'NEVER') {
30
+ // Old NEVER dropped every other field; an explicit empty condition list = never substituted.
31
+ return { conditions: [] };
32
+ }
33
+ if (mode === 'FATIGUE') {
34
+ return {
35
+ ...rest,
36
+ conditions: [fatigueCondition(fatigueBand)],
37
+ conditionLogic: 'ALL',
38
+ pinchServer: false,
39
+ subBackMode: rest.subBackMode ?? 'FATIGUE'
40
+ };
41
+ }
42
+ if (mode === 'PINCH') {
43
+ // A legacy PINCH row without the flag is a serve-and-return pinch server (the documented default).
44
+ return { ...rest, pinchServer: rest.pinchServer ?? true };
45
+ }
46
+ // Unknown legacy mode: strip it and let validation judge the rest.
47
+ return rest;
48
+ }
49
+ /** Convert a legacy DesignatedSub (flat fields + per-set entries); unified shapes pass through. */
50
+ export function convertLegacyDesignatedSub(raw) {
51
+ if (!isRecord(raw))
52
+ return raw;
53
+ const { starter, sets, ...cfg } = raw;
54
+ const flat = convertLegacySetSubConfig(cfg);
55
+ const out = { ...(isRecord(flat) ? flat : {}), starter };
56
+ if (Array.isArray(sets))
57
+ out.sets = sets.map(convertLegacySetSubConfig);
58
+ return out;
59
+ }
60
+ /** Convert ONE legacy libero set-sub config; unified shapes pass through. */
61
+ export function convertLegacyLiberoSetSubConfig(raw) {
62
+ if (!isRecord(raw) || raw.mode == null)
63
+ return raw;
64
+ const { mode, fatigueBand, ...rest } = raw;
65
+ if (mode === 'NEVER')
66
+ return { conditions: [] };
67
+ if (mode === 'ALWAYS')
68
+ return { ...rest, conditions: [{ type: PinchConditionType.ASAP }], conditionLogic: 'ALL' };
69
+ if (mode === 'FATIGUE')
70
+ return { ...rest, conditions: [fatigueCondition(fatigueBand)], conditionLogic: 'ALL' };
71
+ if (mode === 'CONDITIONS')
72
+ return rest;
73
+ return rest;
74
+ }
75
+ /** Convert a legacy LiberoSubConfig (flat fields + per-set entries); unified shapes pass through. */
76
+ export function convertLegacyLiberoSubConfig(raw) {
77
+ if (!isRecord(raw))
78
+ return raw;
79
+ const { sets, ...cfg } = raw;
80
+ const flat = convertLegacyLiberoSetSubConfig(cfg);
81
+ const out = { ...(isRecord(flat) ? flat : {}) };
82
+ if (Array.isArray(sets))
83
+ out.sets = sets.map(convertLegacyLiberoSetSubConfig);
84
+ return out;
85
+ }
@@ -0,0 +1,82 @@
1
+ import { describe, it, expect } from '@jest/globals';
2
+ import { EnergyBand } from './energy-band';
3
+ import { PinchConditionType } from './pinch-condition';
4
+ import { convertLegacyDesignatedSub, convertLegacyLiberoSetSubConfig, convertLegacySetSubConfig } from './sub-config-convert';
5
+ // The conversion matrix for the unified condition engine: every legacy generation must land on the exact
6
+ // unified shape (these functions are the single conversion authority used by the schema preprocess, the
7
+ // transformers, and the API repo's read path).
8
+ describe('convertLegacySetSubConfig', () => {
9
+ it('passes an already-unified config through untouched', () => {
10
+ const unified = { bench: 'X', conditions: [{ type: PinchConditionType.ASAP }], pinchServer: true };
11
+ expect(convertLegacySetSubConfig(unified)).toBe(unified);
12
+ });
13
+ it('converts mode NEVER to an explicit empty condition list, dropping every other field', () => {
14
+ expect(convertLegacySetSubConfig({ mode: 'NEVER', bench: 'X' })).toEqual({ conditions: [] });
15
+ });
16
+ it('converts mode FATIGUE with a band to a FATIGUE condition + FATIGUE sub-back', () => {
17
+ expect(convertLegacySetSubConfig({ mode: 'FATIGUE', fatigueBand: EnergyBand.WORN, bench: 'X', benchFatigueBand: EnergyBand.TIRED })).toEqual({
18
+ bench: 'X',
19
+ benchFatigueBand: EnergyBand.TIRED,
20
+ conditions: [{ type: PinchConditionType.FATIGUE, band: EnergyBand.WORN }],
21
+ conditionLogic: 'ALL',
22
+ pinchServer: false,
23
+ subBackMode: 'FATIGUE'
24
+ });
25
+ });
26
+ it('converts mode FATIGUE without a band to a bandless FATIGUE condition (team default)', () => {
27
+ const out = convertLegacySetSubConfig({ mode: 'FATIGUE' });
28
+ expect(out.conditions).toEqual([{ type: PinchConditionType.FATIGUE }]);
29
+ });
30
+ it('converts mode PINCH keeping conditions and defaulting a missing pinchServer flag to true', () => {
31
+ expect(convertLegacySetSubConfig({ mode: 'PINCH', bench: 'X', conditions: [{ type: PinchConditionType.ASAP }] })).toEqual({
32
+ bench: 'X',
33
+ conditions: [{ type: PinchConditionType.ASAP }],
34
+ pinchServer: true
35
+ });
36
+ });
37
+ it('keeps an explicit pinchServer false on a legacy PINCH regular conditional sub', () => {
38
+ const out = convertLegacySetSubConfig({ mode: 'PINCH', bench: 'X', conditions: [{ type: PinchConditionType.ASAP }], pinchServer: false, subBackMode: 'CONDITIONS', subBackConditions: [{ type: PinchConditionType.ASAP }] });
39
+ expect(out.pinchServer).toBe(false);
40
+ expect(out.subBackMode).toBe('CONDITIONS');
41
+ });
42
+ it('converts the oldest isPinchServer-era row to a pinch server', () => {
43
+ expect(convertLegacySetSubConfig({ isPinchServer: true, bench: 'X', conditions: [{ type: PinchConditionType.ASAP }] })).toEqual({
44
+ bench: 'X',
45
+ conditions: [{ type: PinchConditionType.ASAP }],
46
+ pinchServer: true
47
+ });
48
+ });
49
+ it("converts the oldest 'NEVER' fatigueBand row to never (empty conditions)", () => {
50
+ expect(convertLegacySetSubConfig({ fatigueBand: 'NEVER' })).toEqual({ conditions: [] });
51
+ });
52
+ it('converts the oldest band-only row to a FATIGUE condition', () => {
53
+ const out = convertLegacySetSubConfig({ fatigueBand: EnergyBand.EXHAUSTED });
54
+ expect(out.conditions).toEqual([{ type: PinchConditionType.FATIGUE, band: EnergyBand.EXHAUSTED }]);
55
+ });
56
+ it('strips an unknown legacy mode and keeps the rest (lenient heal)', () => {
57
+ expect(convertLegacySetSubConfig({ mode: 'SOMETIMES', bench: 'X' })).toEqual({ bench: 'X' });
58
+ });
59
+ });
60
+ describe('convertLegacyDesignatedSub', () => {
61
+ it('converts the flat fields and every per-set entry, keeping the starter', () => {
62
+ const out = convertLegacyDesignatedSub({
63
+ starter: 'S',
64
+ mode: 'FATIGUE',
65
+ fatigueBand: EnergyBand.TIRED,
66
+ sets: [{ mode: 'NEVER' }, { mode: 'PINCH', bench: 'X', conditions: [{ type: PinchConditionType.ASAP }] }]
67
+ });
68
+ expect(out.starter).toBe('S');
69
+ expect(out.conditions).toEqual([{ type: PinchConditionType.FATIGUE, band: EnergyBand.TIRED }]);
70
+ expect(out.sets[0]).toEqual({ conditions: [] });
71
+ expect(out.sets[1].pinchServer).toBe(true);
72
+ });
73
+ });
74
+ describe('convertLegacyLiberoSetSubConfig', () => {
75
+ it('maps each legacy libero mode to its unified condition list', () => {
76
+ expect(convertLegacyLiberoSetSubConfig({ mode: 'NEVER' })).toEqual({ conditions: [] });
77
+ expect(convertLegacyLiberoSetSubConfig({ mode: 'ALWAYS' })).toEqual({ conditions: [{ type: PinchConditionType.ASAP }], conditionLogic: 'ALL' });
78
+ expect(convertLegacyLiberoSetSubConfig({ mode: 'FATIGUE', fatigueBand: EnergyBand.WORN })).toEqual({ conditions: [{ type: PinchConditionType.FATIGUE, band: EnergyBand.WORN }], conditionLogic: 'ALL' });
79
+ const conditions = [{ type: PinchConditionType.PHASE, phase: 'RECEIVING' }];
80
+ expect(convertLegacyLiberoSetSubConfig({ mode: 'CONDITIONS', conditions, conditionLogic: 'ANY' })).toEqual({ conditions, conditionLogic: 'ANY' });
81
+ });
82
+ });
@@ -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;
@@ -15,7 +15,7 @@ export class Tactics {
15
15
  }
16
16
  return new Tactics(result.data);
17
17
  }
18
- constructor({ lineup, liberoReplacements, receiveRotationOffset = false, designatedSubs = [], substitutionBand = EnergyBand.TIRED, secondLibero, liberoSub, liberoReplacementSets, rotationSystem = RotationSystemEnum.SIX_ZERO, designatedSetters = [], offensivePreferences = [], systemSets, offensivePreferenceSets, replaceKnockedImmediately = {}, injuryReplacements = [], liberoInjury }) {
18
+ constructor({ lineup, liberoReplacements, receiveRotationOffset = false, designatedSubs = [], substitutionBand = EnergyBand.TIRED, secondLibero, liberoSub, liberoReplacementSets, rotationSystem = RotationSystemEnum.SIX_ZERO, designatedSetters = [], offensivePreferences = [], systemSets, offensivePreferenceSets, replaceKnockedImmediately = {}, injuryReplacements = [], liberoInjury, blockingPreferences = [], blockingPreferenceSets }) {
19
19
  this.lineup = lineup;
20
20
  this.liberoReplacements = liberoReplacements;
21
21
  this.receiveRotationOffset = receiveRotationOffset;
@@ -32,6 +32,8 @@ export class Tactics {
32
32
  this.replaceKnockedImmediately = replaceKnockedImmediately;
33
33
  this.injuryReplacements = injuryReplacements;
34
34
  this.liberoInjury = liberoInjury;
35
+ this.blockingPreferences = blockingPreferences;
36
+ this.blockingPreferenceSets = blockingPreferenceSets;
35
37
  }
36
38
  findPlayerInLineup(id) {
37
39
  if (this.lineup.bench.some(p => p.id === id))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.481",
3
+ "version": "0.0.483",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",