volleyballsimtypes 0.0.507 → 0.0.509

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.
@@ -2,89 +2,90 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.defaultReceiveMap = defaultReceiveMap;
4
4
  exports.defaultBaseConfig = defaultBaseConfig;
5
+ const rotation_system_1 = require("./rotation-system");
5
6
  const lineup_function_1 = require("./lineup-function");
6
7
  const player_1 = require("../player");
7
8
  const match_1 = require("../match");
8
9
  const COORDS = {
9
10
  SERVE: {
10
- 1: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
11
- 2: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
12
- 3: { 1: { d: 10.00, r: -3.50 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 6.50, r: 0.00 } },
13
- 4: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
14
- 5: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
15
- 6: { 1: { d: 10.00, r: -3.50 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 6.50, r: 0.00 } }
11
+ 1: { 1: { d: 10, r: 3.5 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.5 }, 5: { d: 6.5, r: 0 }, 6: { d: 5, r: -2.5 } },
12
+ 2: { 1: { d: 9.8, r: -2.7 }, 2: { d: 0.6, r: 2.35 }, 3: { d: 0.6, r: -2.55 }, 4: { d: 0.5, r: -0.2 }, 5: { d: 5, r: 3.25 }, 6: { d: 7.4, r: 0.15 } },
13
+ 3: { 1: { d: 9.85, r: 3.3 }, 2: { d: 0.55, r: -0.05 }, 3: { d: 0.6, r: 2.45 }, 4: { d: 0.6, r: -2.7 }, 5: { d: 5.3, r: -2.75 }, 6: { d: 5.3, r: 2.7 } },
14
+ 4: { 1: { d: 10, r: 3.5 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.4 }, 5: { d: 6.5, r: 0 }, 6: { d: 5, r: -2.5 } },
15
+ 5: { 1: { d: 9.75, r: 3.25 }, 2: { d: 0.65, r: 2.8 }, 3: { d: 0.8, r: -2.85 }, 4: { d: 0.6, r: 0.05 }, 5: { d: 4.75, r: 2.85 }, 6: { d: 6.95, r: 0 } },
16
+ 6: { 1: { d: 9.8, r: 3.05 }, 2: { d: 0.45, r: 0.05 }, 3: { d: 0.5, r: 2.45 }, 4: { d: 0.45, r: -2.8 }, 5: { d: 4.6, r: -2.65 }, 6: { d: 4.7, r: 3 } }
16
17
  },
17
18
  RECEIVE: {
18
- 1: { 1: { d: 6.50, r: 3.50 }, 2: { d: 6.00, r: 3.00 }, 3: { d: 3.00, r: -3.50 }, 4: { d: 3.50, r: -4.00 }, 5: { d: 6.00, r: -3.00 }, 6: { d: 6.50, r: 0.00 } },
19
- 2: { 1: { d: 6.00, r: 3.00 }, 2: { d: 3.00, r: 4.00 }, 3: { d: 0.50, r: 0.50 }, 4: { d: 6.00, r: -3.00 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 1.25, r: 0.75 } },
20
- 3: { 1: { d: 6.00, r: 3.00 }, 2: { d: 3.00, r: 4.00 }, 3: { d: 6.00, r: -3.00 }, 4: { d: 0.95, r: -4.00 }, 5: { d: 1.00, r: -1.00 }, 6: { d: 6.50, r: 0.00 } },
21
- 4: { 1: { d: 8.50, r: 4.00 }, 2: { d: 6.00, r: -3.00 }, 3: { d: 1.25, r: -4.00 }, 4: { d: 0.75, r: -4.05 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 6.00, r: 3.00 } },
22
- 5: { 1: { d: 6.00, r: 3.00 }, 2: { d: 2.50, r: 4.00 }, 3: { d: 1.00, r: 1.50 }, 4: { d: 6.00, r: -3.00 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 8.50, r: 1.50 } },
23
- 6: { 1: { d: 6.00, r: 3.00 }, 2: { d: 1.00, r: 1.50 }, 3: { d: 6.00, r: -3.00 }, 4: { d: 3.00, r: -4.00 }, 5: { d: 8.50, r: -1.50 }, 6: { d: 6.50, r: 0.00 } }
19
+ 1: { 1: { d: 6.5, r: 3.5 }, 2: { d: 6, r: 3 }, 3: { d: 3, r: -3.5 }, 4: { d: 3.5, r: -4 }, 5: { d: 6, r: -3 }, 6: { d: 6.5, r: 0 } },
20
+ 2: { 1: { d: 5.65, r: 2.3 }, 2: { d: 0.65, r: 2.1 }, 3: { d: 6, r: -2.3 }, 4: { d: 2.75, r: -3.9 }, 5: { d: 7.85, r: -1.7 }, 6: { d: 6.75, r: 0.1 } },
21
+ 3: { 1: { d: 6, r: 3 }, 2: { d: 2.5, r: 3.95 }, 3: { d: 0.75, r: 1 }, 4: { d: 5.55, r: -2.75 }, 5: { d: 6.1, r: 0.1 }, 6: { d: 7.8, r: 1.65 } },
22
+ 4: { 1: { d: 8.5, r: 4 }, 2: { d: 6, r: -3 }, 3: { d: 1.25, r: -4 }, 4: { d: 0.75, r: -4.05 }, 5: { d: 6.5, r: 0 }, 6: { d: 6, r: 3 } },
23
+ 5: { 1: { d: 6.1, r: 2.6 }, 2: { d: 3.25, r: 3.9 }, 3: { d: 5.8, r: -2.75 }, 4: { d: 0.75, r: -3.85 }, 5: { d: 1.9, r: -1.7 }, 6: { d: 6.75, r: -0.1 } },
24
+ 6: { 1: { d: 6, r: 3 }, 2: { d: 2.6, r: 3.85 }, 3: { d: 0.5, r: 0.4 }, 4: { d: 5.9, r: -2.9 }, 5: { d: 6.55, r: 0 }, 6: { d: 1.6, r: 0.9 } }
24
25
  },
25
26
  DEFENCE: {
26
- 1: { 1: { d: 5.00, r: 3.00 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -3.00 } },
27
- 2: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -3.00 }, 6: { d: 5.00, r: 3.00 } },
28
- 3: { 1: { d: 5.00, r: -3.00 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 3.00 }, 6: { d: 7.00, r: 0.00 } },
29
- 4: { 1: { d: 5.00, r: 3.00 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -3.00 } },
30
- 5: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -3.00 }, 6: { d: 5.00, r: 3.00 } },
31
- 6: { 1: { d: 5.00, r: -3.00 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 3.00 }, 6: { d: 7.00, r: 0.00 } }
27
+ 1: { 1: { d: 5, r: 3 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -3 } },
28
+ 2: { 1: { d: 4.9, r: -3 }, 2: { d: 0.6, r: 2.65 }, 3: { d: 0.65, r: -3 }, 4: { d: 0.65, r: -0.1 }, 5: { d: 5, r: 3.05 }, 6: { d: 6.75, r: 0.2 } },
29
+ 3: { 1: { d: 7, r: 0.05 }, 2: { d: 0.5, r: 0.2 }, 3: { d: 0.6, r: 2.65 }, 4: { d: 0.5, r: -2.7 }, 5: { d: 4.7, r: -2.3 }, 6: { d: 4.85, r: 2.6 } },
30
+ 4: { 1: { d: 5, r: 3 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -3 } },
31
+ 5: { 1: { d: 4.8, r: -3.15 }, 2: { d: 0.6, r: 2.5 }, 3: { d: 0.65, r: -2.85 }, 4: { d: 0.65, r: -0.15 }, 5: { d: 5, r: 2.75 }, 6: { d: 6.75, r: 0.05 } },
32
+ 6: { 1: { d: 7.2, r: -0.05 }, 2: { d: 0.45, r: -0.4 }, 3: { d: 0.55, r: 2.45 }, 4: { d: 0.55, r: -3 }, 5: { d: 4.85, r: -2.85 }, 6: { d: 4.8, r: 2.25 } }
32
33
  },
33
34
  DEF_L: {
34
- 1: { 1: { d: 5.00, r: 1.50 }, 2: { d: 0.25, r: -4.00 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8.00, r: -0.50 }, 6: { d: 5.00, r: -4.20 } },
35
- 2: { 1: { d: 8.00, r: -0.50 }, 2: { d: 0.25, r: -3.25 }, 3: { d: 1.75, r: 1.25 }, 4: { d: 0.25, r: -4.00 }, 5: { d: 5.00, r: -4.20 }, 6: { d: 5.00, r: 1.50 } },
36
- 3: { 1: { d: 5.00, r: -4.20 }, 2: { d: 1.75, r: 1.25 }, 3: { d: 0.25, r: -4.00 }, 4: { d: 0.25, r: -3.25 }, 5: { d: 5.00, r: 1.50 }, 6: { d: 8.00, r: -0.50 } },
37
- 4: { 1: { d: 5.00, r: 1.50 }, 2: { d: 0.25, r: -4.00 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8.00, r: -0.50 }, 6: { d: 5.00, r: -4.20 } },
38
- 5: { 1: { d: 8.00, r: -0.50 }, 2: { d: 0.25, r: -3.25 }, 3: { d: 1.75, r: 1.25 }, 4: { d: 0.25, r: -4.00 }, 5: { d: 5.00, r: -4.20 }, 6: { d: 5.00, r: 1.50 } },
39
- 6: { 1: { d: 5.00, r: -4.20 }, 2: { d: 1.75, r: 1.25 }, 3: { d: 0.25, r: -4.00 }, 4: { d: 0.25, r: -3.25 }, 5: { d: 5.00, r: 1.50 }, 6: { d: 8.00, r: -0.50 } }
35
+ 1: { 1: { d: 5, r: 1.5 }, 2: { d: 0.25, r: -4 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8, r: -0.5 }, 6: { d: 5, r: -4.2 } },
36
+ 2: { 1: { d: 4.45, r: -3.95 }, 2: { d: 1.9, r: 1.3 }, 3: { d: 0.4, r: -3.8 }, 4: { d: 0.4, r: -2.9 }, 5: { d: 5.05, r: 2.45 }, 6: { d: 7.6, r: -0.05 } },
37
+ 3: { 1: { d: 8.2, r: -0.7 }, 2: { d: 0.4, r: -2.65 }, 3: { d: 2.1, r: 0.8 }, 4: { d: 0.45, r: -3.8 }, 5: { d: 5.1, r: -3.85 }, 6: { d: 5.2, r: 1.8 } },
38
+ 4: { 1: { d: 5, r: 1.5 }, 2: { d: 0.25, r: -4 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8, r: -0.5 }, 6: { d: 5, r: -4.2 } },
39
+ 5: { 1: { d: 5.05, r: -3.9 }, 2: { d: 2.2, r: 0.65 }, 3: { d: 0.65, r: -3.8 }, 4: { d: 0.65, r: -2.75 }, 5: { d: 4.65, r: 1.1 }, 6: { d: 7.7, r: -0.75 } },
40
+ 6: { 1: { d: 7.15, r: 0.25 }, 2: { d: 0.5, r: -2.7 }, 3: { d: 1.8, r: 1.1 }, 4: { d: 0.5, r: -3.8 }, 5: { d: 4.75, r: -3.85 }, 6: { d: 4.95, r: 1.6 } }
40
41
  },
41
42
  DEF_M: {
42
- 1: { 1: { d: 5.00, r: 2.50 }, 2: { d: 1.75, r: -2.50 }, 3: { d: 0.25, r: 0.00 }, 4: { d: 1.75, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
43
- 2: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.25, r: 0.00 }, 3: { d: 1.75, r: 2.50 }, 4: { d: 1.75, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
44
- 3: { 1: { d: 5.00, r: -2.50 }, 2: { d: 1.75, r: 2.50 }, 3: { d: 1.75, r: -2.50 }, 4: { d: 0.25, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 7.00, r: 0.00 } },
45
- 4: { 1: { d: 5.00, r: 2.50 }, 2: { d: 1.75, r: -2.50 }, 3: { d: 0.25, r: 0.00 }, 4: { d: 1.75, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
46
- 5: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.25, r: 0.00 }, 3: { d: 1.75, r: 2.50 }, 4: { d: 1.75, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
47
- 6: { 1: { d: 5.00, r: -2.50 }, 2: { d: 1.75, r: 2.50 }, 3: { d: 1.75, r: -2.50 }, 4: { d: 0.25, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 7.00, r: 0.00 } }
43
+ 1: { 1: { d: 5, r: 2.5 }, 2: { d: 1.75, r: -2.5 }, 3: { d: 0.25, r: 0 }, 4: { d: 1.75, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -2.5 } },
44
+ 2: { 1: { d: 5, r: -2.8 }, 2: { d: 1.85, r: 2.5 }, 3: { d: 1.85, r: -2.4 }, 4: { d: 0.4, r: 0.15 }, 5: { d: 5, r: 2.65 }, 6: { d: 7, r: 0.05 } },
45
+ 3: { 1: { d: 7.15, r: 0.1 }, 2: { d: 0.5, r: 0.1 }, 3: { d: 1.95, r: 2.45 }, 4: { d: 1.8, r: -2.55 }, 5: { d: 5.25, r: -2.45 }, 6: { d: 5.2, r: 2.8 } },
46
+ 4: { 1: { d: 5, r: 2.5 }, 2: { d: 1.75, r: -2.5 }, 3: { d: 0.25, r: 0 }, 4: { d: 1.75, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -2.5 } },
47
+ 5: { 1: { d: 4.9, r: -2.35 }, 2: { d: 1.95, r: 2.4 }, 3: { d: 1.85, r: -2.6 }, 4: { d: 0.55, r: -0.2 }, 5: { d: 4.9, r: 2.45 }, 6: { d: 6.7, r: -0.1 } },
48
+ 6: { 1: { d: 7.35, r: 0.05 }, 2: { d: 0.6, r: 0.1 }, 3: { d: 2, r: 2.45 }, 4: { d: 2.25, r: -1.95 }, 5: { d: 5.2, r: -2.05 }, 6: { d: 5.3, r: 2.5 } }
48
49
  },
49
50
  DEF_R: {
50
- 1: { 1: { d: 5.00, r: 4.20 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4.00 }, 5: { d: 8.00, r: 0.50 }, 6: { d: 5.00, r: -1.50 } },
51
- 2: { 1: { d: 8.00, r: 0.50 }, 2: { d: 0.25, r: 3.25 }, 3: { d: 0.25, r: 4.00 }, 4: { d: 1.75, r: -1.25 }, 5: { d: 5.00, r: -1.50 }, 6: { d: 5.00, r: 4.20 } },
52
- 3: { 1: { d: 5.00, r: -1.50 }, 2: { d: 0.25, r: 4.00 }, 3: { d: 1.75, r: -1.25 }, 4: { d: 0.25, r: 3.25 }, 5: { d: 5.00, r: 4.20 }, 6: { d: 8.00, r: 0.50 } },
53
- 4: { 1: { d: 5.00, r: 4.20 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4.00 }, 5: { d: 8.00, r: 0.50 }, 6: { d: 5.00, r: -1.50 } },
54
- 5: { 1: { d: 8.00, r: 0.50 }, 2: { d: 0.25, r: 3.25 }, 3: { d: 0.25, r: 4.00 }, 4: { d: 1.75, r: -1.25 }, 5: { d: 5.00, r: -1.50 }, 6: { d: 5.00, r: 4.20 } },
55
- 6: { 1: { d: 5.00, r: -1.50 }, 2: { d: 0.25, r: 4.00 }, 3: { d: 1.75, r: -1.25 }, 4: { d: 0.25, r: 3.25 }, 5: { d: 5.00, r: 4.20 }, 6: { d: 8.00, r: 0.50 } }
51
+ 1: { 1: { d: 5, r: 4.2 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4 }, 5: { d: 8, r: 0.5 }, 6: { d: 5, r: -1.5 } },
52
+ 2: { 1: { d: 4.65, r: -1 }, 2: { d: 0.25, r: 3.85 }, 3: { d: 1.75, r: -1.4 }, 4: { d: 0.3, r: 2.95 }, 5: { d: 4.3, r: 3.95 }, 6: { d: 8.15, r: 0.5 } },
53
+ 3: { 1: { d: 8.05, r: 0.4 }, 2: { d: 0.4, r: 2.95 }, 3: { d: 0.4, r: 3.85 }, 4: { d: 2, r: -2 }, 5: { d: 4.65, r: -1.15 }, 6: { d: 4.75, r: 4 } },
54
+ 4: { 1: { d: 5, r: 4.2 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4 }, 5: { d: 8, r: 0.5 }, 6: { d: 5, r: -1.5 } },
55
+ 5: { 1: { d: 5.35, r: -2 }, 2: { d: 0.5, r: 3.65 }, 3: { d: 2.1, r: -1.25 }, 4: { d: 0.5, r: 2.6 }, 5: { d: 5.4, r: 3.85 }, 6: { d: 7.75, r: -0.15 } },
56
+ 6: { 1: { d: 7.8, r: 0.75 }, 2: { d: 0.45, r: 2.9 }, 3: { d: 0.45, r: 3.95 }, 4: { d: 1.75, r: -0.25 }, 5: { d: 5.15, r: -1.4 }, 6: { d: 4.9, r: 4 } }
56
57
  },
57
58
  ATTACK: {
58
- 1: { 1: { d: 0.50, r: 1.50 }, 2: { d: 3.75, r: -5.00 }, 3: { d: 3.00, r: 0.25 }, 4: { d: 3.75, r: 5.00 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 4.50, r: -2.50 } },
59
- 2: { 1: { d: 6.50, r: 0.00 }, 2: { d: 3.00, r: 0.25 }, 3: { d: 3.75, r: 5.00 }, 4: { d: 3.75, r: -5.00 }, 5: { d: 4.50, r: -2.50 }, 6: { d: 0.50, r: 1.50 } },
60
- 3: { 1: { d: 4.50, r: -2.50 }, 2: { d: 3.75, r: 5.00 }, 3: { d: 3.75, r: -5.00 }, 4: { d: 3.00, r: 0.25 }, 5: { d: 0.50, r: 1.50 }, 6: { d: 6.50, r: 0.00 } },
61
- 4: { 1: { d: 6.50, r: 4.90 }, 2: { d: 3.75, r: -5.00 }, 3: { d: 3.00, r: 0.25 }, 4: { d: 0.50, r: 1.50 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 4.50, r: -2.50 } },
62
- 5: { 1: { d: 6.50, r: 0.00 }, 2: { d: 3.00, r: 0.25 }, 3: { d: 0.50, r: 1.50 }, 4: { d: 3.75, r: -5.00 }, 5: { d: 4.50, r: -2.50 }, 6: { d: 6.50, r: 4.90 } },
63
- 6: { 1: { d: 4.50, r: -2.50 }, 2: { d: 0.50, r: 1.50 }, 3: { d: 3.75, r: -5.00 }, 4: { d: 3.00, r: 0.25 }, 5: { d: 6.50, r: 4.90 }, 6: { d: 6.50, r: 0.00 } }
59
+ 1: { 1: { d: 0.5, r: 1.5 }, 2: { d: 3.75, r: -5 }, 3: { d: 3, r: 0.25 }, 4: { d: 3.75, r: 5 }, 5: { d: 6.5, r: 0 }, 6: { d: 4.5, r: -2.5 } },
60
+ 2: { 1: { d: 5.1, r: -2 }, 2: { d: 0.45, r: 1.55 }, 3: { d: 3.6, r: -5.2 }, 4: { d: 2.8, r: 0.2 }, 5: { d: 6.4, r: 5.05 }, 6: { d: 6.55, r: -0.6 } },
61
+ 3: { 1: { d: 6.5, r: -0.15 }, 2: { d: 3, r: 0.35 }, 3: { d: 0.5, r: 1.6 }, 4: { d: 2.4, r: -5.15 }, 5: { d: 4.6, r: -2.55 }, 6: { d: 5.4, r: 5.2 } },
62
+ 4: { 1: { d: 6.5, r: 4.9 }, 2: { d: 3.75, r: -5 }, 3: { d: 3, r: 0.25 }, 4: { d: 0.5, r: 1.5 }, 5: { d: 6.5, r: 0 }, 6: { d: 4.5, r: -2.5 } },
63
+ 5: { 1: { d: 4.65, r: -2.35 }, 2: { d: 3.65, r: 4.8 }, 3: { d: 2.9, r: -5.15 }, 4: { d: 3.05, r: 0.4 }, 5: { d: 0.75, r: 1.7 }, 6: { d: 6.4, r: -0.05 } },
64
+ 6: { 1: { d: 6.2, r: -0.4 }, 2: { d: 3, r: 0.2 }, 3: { d: 3.65, r: 5.2 }, 4: { d: 3.55, r: -5.2 }, 5: { d: 4.5, r: -2.45 }, 6: { d: 0.65, r: 1.3 } }
64
65
  },
65
66
  ATK_L: {
66
- 1: { 1: { d: 0.75, r: 0.00 }, 2: { d: 0.50, r: -4.00 }, 3: { d: 1.00, r: -2.50 }, 4: { d: 3.50, r: 0.75 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.50, r: -4.00 } },
67
- 2: { 1: { d: 6.25, r: -0.75 }, 2: { d: 1.00, r: -2.50 }, 3: { d: 3.50, r: 0.75 }, 4: { d: 0.50, r: -4.00 }, 5: { d: 3.50, r: -4.00 }, 6: { d: 0.75, r: 0.00 } },
68
- 3: { 1: { d: 3.50, r: -4.00 }, 2: { d: 3.50, r: 0.75 }, 3: { d: 0.50, r: -4.00 }, 4: { d: 1.00, r: -2.50 }, 5: { d: 0.75, r: 0.00 }, 6: { d: 6.25, r: -0.75 } },
69
- 4: { 1: { d: 3.50, r: 0.75 }, 2: { d: 0.50, r: -4.00 }, 3: { d: 1.00, r: -2.50 }, 4: { d: 0.75, r: 0.00 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.50, r: -4.00 } },
70
- 5: { 1: { d: 6.25, r: -0.75 }, 2: { d: 1.00, r: -2.50 }, 3: { d: 0.75, r: 0.00 }, 4: { d: 0.50, r: -4.00 }, 5: { d: 3.50, r: -4.00 }, 6: { d: 3.50, r: 0.75 } },
71
- 6: { 1: { d: 3.50, r: -4.00 }, 2: { d: 0.75, r: 0.00 }, 3: { d: 0.50, r: -4.00 }, 4: { d: 1.00, r: -2.50 }, 5: { d: 3.50, r: 0.75 }, 6: { d: 6.25, r: -0.75 } }
67
+ 1: { 1: { d: 0.75, r: 0 }, 2: { d: 0.5, r: -4 }, 3: { d: 1, r: -2.5 }, 4: { d: 3.5, r: 0.75 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.5, r: -4 } },
68
+ 2: { 1: { d: 3.4, r: -4.05 }, 2: { d: 0.75, r: 0 }, 3: { d: 0.9, r: -4.15 }, 4: { d: 1.8, r: -2.5 }, 5: { d: 3.4, r: 0.5 }, 6: { d: 6.5, r: -1.15 } },
69
+ 3: { 1: { d: 6.35, r: -0.1 }, 2: { d: 2.1, r: -2.45 }, 3: { d: 0.9, r: 0 }, 4: { d: 0.8, r: -3.95 }, 5: { d: 4.6, r: -3.75 }, 6: { d: 3.6, r: 1.45 } },
70
+ 4: { 1: { d: 3.5, r: 0.75 }, 2: { d: 0.5, r: -4 }, 3: { d: 1, r: -2.5 }, 4: { d: 0.75, r: 0 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.5, r: -4 } },
71
+ 5: { 1: { d: 4.25, r: -3.85 }, 2: { d: 3.55, r: 0.75 }, 3: { d: 1, r: -4.1 }, 4: { d: 2.05, r: -2.65 }, 5: { d: 0.85, r: -0.15 }, 6: { d: 6, r: -0.8 } },
72
+ 6: { 1: { d: 5.9, r: -1 }, 2: { d: 1.05, r: -2.5 }, 3: { d: 3.45, r: 0.9 }, 4: { d: 0.7, r: -3.9 }, 5: { d: 3.4, r: -4.05 }, 6: { d: 0.75, r: -0.2 } }
72
73
  },
73
74
  ATK_M: {
74
- 1: { 1: { d: 0.75, r: 1.25 }, 2: { d: 1.25, r: -2.00 }, 3: { d: 0.75, r: 0.50 }, 4: { d: 2.25, r: 2.60 }, 5: { d: 6.50, r: 1.50 }, 6: { d: 4.00, r: -1.50 } },
75
- 2: { 1: { d: 6.50, r: 1.50 }, 2: { d: 0.75, r: 0.50 }, 3: { d: 2.25, r: 2.60 }, 4: { d: 1.25, r: -2.00 }, 5: { d: 4.00, r: -1.50 }, 6: { d: 0.75, r: 1.25 } },
76
- 3: { 1: { d: 4.00, r: -1.50 }, 2: { d: 2.25, r: 2.60 }, 3: { d: 1.25, r: -2.00 }, 4: { d: 0.75, r: 0.50 }, 5: { d: 0.75, r: 1.25 }, 6: { d: 6.50, r: 1.50 } },
77
- 4: { 1: { d: 2.25, r: 2.60 }, 2: { d: 1.25, r: -2.00 }, 3: { d: 0.75, r: 0.50 }, 4: { d: 0.75, r: 1.25 }, 5: { d: 6.50, r: 1.50 }, 6: { d: 4.00, r: -1.50 } },
78
- 5: { 1: { d: 6.50, r: 1.50 }, 2: { d: 0.75, r: 0.50 }, 3: { d: 0.75, r: 1.25 }, 4: { d: 1.25, r: -2.00 }, 5: { d: 4.00, r: -1.50 }, 6: { d: 2.25, r: 2.60 } },
79
- 6: { 1: { d: 4.00, r: -1.50 }, 2: { d: 0.75, r: 1.25 }, 3: { d: 1.25, r: -2.00 }, 4: { d: 0.75, r: 0.50 }, 5: { d: 2.25, r: 2.60 }, 6: { d: 6.50, r: 1.50 } }
75
+ 1: { 1: { d: 0.75, r: 1.25 }, 2: { d: 1.25, r: -2 }, 3: { d: 0.75, r: 0.5 }, 4: { d: 2.25, r: 2.6 }, 5: { d: 6.5, r: 1.5 }, 6: { d: 4, r: -1.5 } },
76
+ 2: { 1: { d: 4.5, r: -2.2 }, 2: { d: 0.7, r: 1.25 }, 3: { d: 1.8, r: -2.45 }, 4: { d: 0.9, r: 0.05 }, 5: { d: 2.75, r: 3.05 }, 6: { d: 5.75, r: 0 } },
77
+ 3: { 1: { d: 6.55, r: 1.15 }, 2: { d: 0.9, r: 0.3 }, 3: { d: 0.85, r: 1.45 }, 4: { d: 1.7, r: -2.7 }, 5: { d: 3.95, r: -1.75 }, 6: { d: 2.25, r: 3.2 } },
78
+ 4: { 1: { d: 2.25, r: 2.6 }, 2: { d: 1.25, r: -2 }, 3: { d: 0.75, r: 0.5 }, 4: { d: 0.75, r: 1.25 }, 5: { d: 6.5, r: 1.5 }, 6: { d: 4, r: -1.5 } },
79
+ 5: { 1: { d: 4.35, r: -1.5 }, 2: { d: 2.25, r: 2.85 }, 3: { d: 1.9, r: -2.55 }, 4: { d: 0.8, r: 0.35 }, 5: { d: 0.6, r: 1.45 }, 6: { d: 5.55, r: 1.45 } },
80
+ 6: { 1: { d: 5.2, r: 1.1 }, 2: { d: 0.8, r: 0.35 }, 3: { d: 2.4, r: 3 }, 4: { d: 1.8, r: -2.15 }, 5: { d: 4.5, r: -1.7 }, 6: { d: 0.8, r: 1.35 } }
80
81
  },
81
82
  ATK_R: {
82
- 1: { 1: { d: 1.75, r: 2.50 }, 2: { d: 1.50, r: -1.75 }, 3: { d: 0.75, r: 1.75 }, 4: { d: 0.50, r: 4.00 }, 5: { d: 5.00, r: 3.25 }, 6: { d: 5.75, r: -2.00 } },
83
- 2: { 1: { d: 5.00, r: 3.25 }, 2: { d: 0.75, r: 1.75 }, 3: { d: 0.50, r: 4.00 }, 4: { d: 1.50, r: -1.75 }, 5: { d: 5.75, r: -2.00 }, 6: { d: 1.75, r: 2.50 } },
84
- 3: { 1: { d: 5.75, r: -2.00 }, 2: { d: 0.50, r: 4.00 }, 3: { d: 1.50, r: -1.75 }, 4: { d: 0.75, r: 1.75 }, 5: { d: 1.75, r: 2.50 }, 6: { d: 5.00, r: 3.25 } },
85
- 4: { 1: { d: 2.25, r: 4.00 }, 2: { d: 2.25, r: -1.75 }, 3: { d: 0.75, r: 1.50 }, 4: { d: 1.50, r: 2.25 }, 5: { d: 6.00, r: 2.25 }, 6: { d: 5.00, r: -0.75 } },
86
- 5: { 1: { d: 6.00, r: 2.25 }, 2: { d: 0.75, r: 1.50 }, 3: { d: 1.50, r: 2.25 }, 4: { d: 2.25, r: -1.75 }, 5: { d: 5.00, r: -0.75 }, 6: { d: 2.25, r: 4.00 } },
87
- 6: { 1: { d: 5.00, r: -0.75 }, 2: { d: 1.50, r: 2.25 }, 3: { d: 2.25, r: -1.75 }, 4: { d: 0.75, r: 1.50 }, 5: { d: 2.25, r: 4.00 }, 6: { d: 6.00, r: 2.25 } }
83
+ 1: { 1: { d: 1.75, r: 2.5 }, 2: { d: 1.5, r: -1.75 }, 3: { d: 0.75, r: 1.75 }, 4: { d: 0.5, r: 4 }, 5: { d: 5, r: 3.25 }, 6: { d: 5.75, r: -2 } },
84
+ 2: { 1: { d: 4.65, r: -0.8 }, 2: { d: 0.75, r: 1.75 }, 3: { d: 1.85, r: -1.75 }, 4: { d: 1.7, r: 2.2 }, 5: { d: 2.15, r: 4.25 }, 6: { d: 6.25, r: 2 } },
85
+ 3: { 1: { d: 5.1, r: 3.15 }, 2: { d: 1.85, r: 2.6 }, 3: { d: 0.8, r: 1.75 }, 4: { d: 2.15, r: -1.7 }, 5: { d: 4.9, r: -1.25 }, 6: { d: 1.9, r: 4.15 } },
86
+ 4: { 1: { d: 2.25, r: 4 }, 2: { d: 2.25, r: -1.75 }, 3: { d: 0.75, r: 1.5 }, 4: { d: 1.5, r: 2.25 }, 5: { d: 6, r: 2.25 }, 6: { d: 5, r: -0.75 } },
87
+ 5: { 1: { d: 5.95, r: -2 }, 2: { d: 0.9, r: 3.7 }, 3: { d: 2.2, r: -1.6 }, 4: { d: 2, r: 2.35 }, 5: { d: 0.9, r: 1.15 }, 6: { d: 6, r: 1.9 } },
88
+ 6: { 1: { d: 5.35, r: 2.35 }, 2: { d: 2.05, r: 2.1 }, 3: { d: 0.8, r: 4 }, 4: { d: 2.1, r: -1.95 }, 5: { d: 4.9, r: -1.4 }, 6: { d: 0.4, r: 1.3 } }
88
89
  }
89
90
  };
90
91
  // The default coordinate table as a BaseConfig.coords (jsonb string keys). Shared, readonly; materialized (and so
@@ -101,36 +102,47 @@ const DEFAULT_COORDS = (() => {
101
102
  }
102
103
  return out;
103
104
  })();
104
- // The owner's authored per-point-of-attack block map for the 5-1 (owner 2026-08-07), keyed
105
+ // The owner's corrected per-point-of-attack block map for the 5-1 (exported 2026-08-09), keyed
105
106
  // [DEF_L|DEF_M|DEF_R][rotation][zone] -> canBlock. `false` = that front-row zone sits OUT of the block for an attack
106
- // from that side; `true` = reads/joins the wall. Only front-row zones (2/3/4) are tagged. Same rotation convention
107
- // as DEFAULT_COORDS. Generated from the finalized 5-1 sr-mapper preset's Def L/M/R block/noblock tags.
107
+ // from that side; `true` = reads/joins the wall. Only the front-row zones in play for the rotation are tagged. Same
108
+ // rotation convention as DEFAULT_COORDS.
108
109
  const DEFAULT_BLOCKING = {
109
110
  DEF_L: {
110
111
  1: { 2: true, 3: true, 4: false },
111
- 2: { 2: true, 3: false, 4: true },
112
- 3: { 2: false, 3: true, 4: true },
112
+ 2: { 2: false, 4: true },
113
+ 3: { 3: false, 4: true },
113
114
  4: { 2: true, 3: true, 4: false },
114
- 5: { 2: true, 3: false, 4: true },
115
- 6: { 2: false, 3: true, 4: true }
115
+ 5: { 2: false, 4: true },
116
+ 6: { 3: false, 4: true }
116
117
  },
117
118
  DEF_M: {
118
119
  1: { 2: false, 3: true, 4: false },
119
- 2: { 2: true, 3: false, 4: false },
120
- 3: { 2: false, 3: false, 4: true },
120
+ 2: { 2: false, 3: false },
121
+ 3: { 3: false, 4: false },
121
122
  4: { 2: false, 3: true, 4: false },
122
- 5: { 2: true, 3: false, 4: false },
123
- 6: { 2: false, 3: false, 4: true }
123
+ 5: { 2: false, 3: false },
124
+ 6: { 3: false, 4: false }
124
125
  },
125
126
  DEF_R: {
126
127
  1: { 2: false, 3: true, 4: true },
127
- 2: { 2: true, 3: true, 4: false },
128
- 3: { 2: true, 3: false, 4: true },
128
+ 2: { 2: true, 3: false },
129
+ 3: { 2: true, 4: false },
129
130
  4: { 2: false, 3: true, 4: true },
130
- 5: { 2: true, 3: true, 4: false },
131
- 6: { 2: true, 3: false, 4: true }
131
+ 5: { 2: true, 3: false },
132
+ 6: { 2: true, 4: false }
132
133
  }
133
134
  };
135
+ // The owner's corrected 5-1 serve-receive participation map (exported 2026-08-09). The 5-1 uses this exact map; the
136
+ // other systems derive their 3-passer map from slot functions (defaultReceiveMap) since their receiving personnel
137
+ // differ. Keyed [rotation][zone] -> passes.
138
+ const DEFAULT_5_1_RECEIVE = {
139
+ 1: { 1: false, 2: true, 3: false, 4: false, 5: true, 6: true },
140
+ 2: { 1: true, 2: false, 3: true, 4: false, 5: false, 6: true },
141
+ 3: { 1: true, 2: false, 3: false, 4: true, 5: true, 6: false },
142
+ 4: { 1: false, 2: true, 3: false, 4: false, 5: true, 6: true },
143
+ 5: { 1: true, 2: false, 3: true, 4: false, 5: false, 6: true },
144
+ 6: { 1: true, 2: false, 3: false, 4: true, 5: true, 6: false }
145
+ };
134
146
  // Rotation index -> the setter's rotational zone (inverse of SETTER_ZONE_TO_ROTATION {1:1,6:2,5:3,4:4,3:5,2:6}).
135
147
  const ROTATION_TO_SETTER_ZONE = { 1: 1, 2: 6, 3: 5, 4: 4, 5: 3, 6: 2 };
136
148
  // The default serve-receive participation map: the standard 3-passer formation. A rotational slot passes iff its
@@ -151,8 +163,9 @@ function defaultReceiveMap(system) {
151
163
  return receive;
152
164
  }
153
165
  // The default base config a team of the given system starts with. Every team always has one (materialized on team
154
- // creation and by the backfill migration); the coordinates are the same 5-1 table for every system, only the
155
- // receive map is derived per system.
166
+ // creation and by the backfill migration). Every system reuses the corrected 5-1 coordinate table and block map; the
167
+ // 5-1 uses the owner's exported receive map, the other systems derive their receive map per system.
156
168
  function defaultBaseConfig(system) {
157
- return { coords: DEFAULT_COORDS, receive: defaultReceiveMap(system), blocking: DEFAULT_BLOCKING };
169
+ const receive = system === rotation_system_1.RotationSystemEnum.FIVE_ONE ? DEFAULT_5_1_RECEIVE : defaultReceiveMap(system);
170
+ return { coords: DEFAULT_COORDS, receive, blocking: DEFAULT_BLOCKING };
158
171
  }
@@ -4,6 +4,7 @@ export * from './formation';
4
4
  export * from './tactics';
5
5
  export * from './base-config';
6
6
  export * from './default-base-config';
7
+ export * from './receive-overlap';
7
8
  export * from './team-name';
8
9
  export * from './energy-band';
9
10
  export * from './pinch-condition';
@@ -20,6 +20,7 @@ __exportStar(require("./formation"), exports);
20
20
  __exportStar(require("./tactics"), exports);
21
21
  __exportStar(require("./base-config"), exports);
22
22
  __exportStar(require("./default-base-config"), exports);
23
+ __exportStar(require("./receive-overlap"), exports);
23
24
  __exportStar(require("./team-name"), exports);
24
25
  __exportStar(require("./energy-band"), exports);
25
26
  __exportStar(require("./pinch-condition"), exports);
@@ -0,0 +1,33 @@
1
+ import { BaseConfig } from './base-config';
2
+ export interface ReceiveOverlapViolation {
3
+ /** Rotation (1..6) that has at least one violation. */
4
+ readonly rotation: number;
5
+ /** The rotational zones (1..6) involved in a violation, to flag in the editor. */
6
+ readonly zones: number[];
7
+ /** Human-readable violation messages for that rotation. */
8
+ readonly messages: string[];
9
+ }
10
+ /**
11
+ * Returns every RECEIVE rotation that breaks the overlap rule (empty if the whole receive formation is legal).
12
+ * A missing RECEIVE map or a missing zone is skipped rather than flagged, so partial/legacy configs never throw.
13
+ */
14
+ export declare function receiveOverlapViolations(config: BaseConfig): ReceiveOverlapViolation[];
15
+ /** True when the RECEIVE formation of `config` respects the overlap rule in every rotation. */
16
+ export declare function isReceiveOverlapLegal(config: BaseConfig): boolean;
17
+ /**
18
+ * Returns every SERVE rotation whose server (zone 1) is NOT behind the end line (owner 2026-08-10: on Serve, only
19
+ * the server is constrained; the rest of the serving formation is free). A missing SERVE map or zone-1 coord is
20
+ * skipped rather than flagged, so partial/legacy configs never throw.
21
+ */
22
+ export declare function serveLineViolations(config: BaseConfig): ReceiveOverlapViolation[];
23
+ /** A base-config rule violation, tagged with the formation it belongs to so the editor/API can point at it. */
24
+ export interface FormationViolation extends ReceiveOverlapViolation {
25
+ readonly formation: 'RECEIVE' | 'SERVE';
26
+ }
27
+ /**
28
+ * Every base-config rule violation across the constrained formations: the RECEIVE overlap rule and the SERVE
29
+ * server-behind-the-line rule. This is the single check the tactics save (UI + API) and the editor flagging share.
30
+ */
31
+ export declare function baseConfigViolations(config: BaseConfig): FormationViolation[];
32
+ /** True when `config` breaks no RECEIVE overlap rule and no SERVE server-line rule. */
33
+ export declare function isBaseConfigLegal(config: BaseConfig): boolean;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.receiveOverlapViolations = receiveOverlapViolations;
4
+ exports.isReceiveOverlapLegal = isReceiveOverlapLegal;
5
+ exports.serveLineViolations = serveLineViolations;
6
+ exports.baseConfigViolations = baseConfigViolations;
7
+ exports.isBaseConfigLegal = isBaseConfigLegal;
8
+ /**
9
+ * Returns every RECEIVE rotation that breaks the overlap rule (empty if the whole receive formation is legal).
10
+ * A missing RECEIVE map or a missing zone is skipped rather than flagged, so partial/legacy configs never throw.
11
+ */
12
+ function receiveOverlapViolations(config) {
13
+ const rc = config.coords?.RECEIVE;
14
+ if (rc == null)
15
+ return [];
16
+ const out = [];
17
+ for (let rot = 1; rot <= 6; rot++) {
18
+ const row = rc[String(rot)];
19
+ if (row == null)
20
+ continue;
21
+ const at = (zone) => row[String(zone)];
22
+ const bad = new Set();
23
+ const messages = [];
24
+ const lateral = (left, right, ln, rn) => {
25
+ const a = at(left);
26
+ const b = at(right);
27
+ if (a == null || b == null)
28
+ return;
29
+ if (a.r >= b.r) {
30
+ bad.add(left);
31
+ bad.add(right);
32
+ messages.push(`${ln} must be left of ${rn}`);
33
+ }
34
+ };
35
+ const depth = (front, back, fn, bn) => {
36
+ const a = at(front);
37
+ const b = at(back);
38
+ if (a == null || b == null)
39
+ return;
40
+ if (a.d >= b.d) {
41
+ bad.add(front);
42
+ bad.add(back);
43
+ messages.push(`${fn} must be in front of ${bn}`);
44
+ }
45
+ };
46
+ lateral(4, 3, 'left-front', 'middle-front');
47
+ lateral(3, 2, 'middle-front', 'right-front');
48
+ lateral(5, 6, 'left-back', 'middle-back');
49
+ lateral(6, 1, 'middle-back', 'right-back');
50
+ depth(2, 1, 'right-front', 'right-back');
51
+ depth(3, 6, 'middle-front', 'middle-back');
52
+ depth(4, 5, 'left-front', 'left-back');
53
+ if (bad.size > 0)
54
+ out.push({ rotation: rot, zones: [...bad].sort((a, b) => a - b), messages });
55
+ }
56
+ return out;
57
+ }
58
+ /** True when the RECEIVE formation of `config` respects the overlap rule in every rotation. */
59
+ function isReceiveOverlapLegal(config) {
60
+ return receiveOverlapViolations(config).length === 0;
61
+ }
62
+ // The end line sits 9 m off the net (the FIVB court depth; matches the court editor's END_LINE). A server must
63
+ // contact the ball from BEHIND it, so on the SERVE formation the server (rotational zone 1) must have d >= this.
64
+ const END_LINE_DEPTH = 9;
65
+ /**
66
+ * Returns every SERVE rotation whose server (zone 1) is NOT behind the end line (owner 2026-08-10: on Serve, only
67
+ * the server is constrained; the rest of the serving formation is free). A missing SERVE map or zone-1 coord is
68
+ * skipped rather than flagged, so partial/legacy configs never throw.
69
+ */
70
+ function serveLineViolations(config) {
71
+ const sc = config.coords?.SERVE;
72
+ if (sc == null)
73
+ return [];
74
+ const out = [];
75
+ for (let rot = 1; rot <= 6; rot++) {
76
+ const server = sc[String(rot)]?.['1'];
77
+ if (server == null)
78
+ continue;
79
+ if (server.d < END_LINE_DEPTH)
80
+ out.push({ rotation: rot, zones: [1], messages: ['server must be behind the end line'] });
81
+ }
82
+ return out;
83
+ }
84
+ /**
85
+ * Every base-config rule violation across the constrained formations: the RECEIVE overlap rule and the SERVE
86
+ * server-behind-the-line rule. This is the single check the tactics save (UI + API) and the editor flagging share.
87
+ */
88
+ function baseConfigViolations(config) {
89
+ return [
90
+ ...receiveOverlapViolations(config).map(v => ({ ...v, formation: 'RECEIVE' })),
91
+ ...serveLineViolations(config).map(v => ({ ...v, formation: 'SERVE' }))
92
+ ];
93
+ }
94
+ /** True when `config` breaks no RECEIVE overlap rule and no SERVE server-line rule. */
95
+ function isBaseConfigLegal(config) {
96
+ return baseConfigViolations(config).length === 0;
97
+ }
@@ -1,86 +1,87 @@
1
+ import { RotationSystemEnum } from './rotation-system';
1
2
  import { slotFunctionAt } from './lineup-function';
2
3
  import { RoleEnum } from '../player';
3
4
  import { isBackRow } from '../match';
4
5
  const COORDS = {
5
6
  SERVE: {
6
- 1: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
7
- 2: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
8
- 3: { 1: { d: 10.00, r: -3.50 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 6.50, r: 0.00 } },
9
- 4: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
10
- 5: { 1: { d: 10.00, r: 3.50 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
11
- 6: { 1: { d: 10.00, r: -3.50 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 6.50, r: 0.00 } }
7
+ 1: { 1: { d: 10, r: 3.5 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.5 }, 5: { d: 6.5, r: 0 }, 6: { d: 5, r: -2.5 } },
8
+ 2: { 1: { d: 9.8, r: -2.7 }, 2: { d: 0.6, r: 2.35 }, 3: { d: 0.6, r: -2.55 }, 4: { d: 0.5, r: -0.2 }, 5: { d: 5, r: 3.25 }, 6: { d: 7.4, r: 0.15 } },
9
+ 3: { 1: { d: 9.85, r: 3.3 }, 2: { d: 0.55, r: -0.05 }, 3: { d: 0.6, r: 2.45 }, 4: { d: 0.6, r: -2.7 }, 5: { d: 5.3, r: -2.75 }, 6: { d: 5.3, r: 2.7 } },
10
+ 4: { 1: { d: 10, r: 3.5 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.4 }, 5: { d: 6.5, r: 0 }, 6: { d: 5, r: -2.5 } },
11
+ 5: { 1: { d: 9.75, r: 3.25 }, 2: { d: 0.65, r: 2.8 }, 3: { d: 0.8, r: -2.85 }, 4: { d: 0.6, r: 0.05 }, 5: { d: 4.75, r: 2.85 }, 6: { d: 6.95, r: 0 } },
12
+ 6: { 1: { d: 9.8, r: 3.05 }, 2: { d: 0.45, r: 0.05 }, 3: { d: 0.5, r: 2.45 }, 4: { d: 0.45, r: -2.8 }, 5: { d: 4.6, r: -2.65 }, 6: { d: 4.7, r: 3 } }
12
13
  },
13
14
  RECEIVE: {
14
- 1: { 1: { d: 6.50, r: 3.50 }, 2: { d: 6.00, r: 3.00 }, 3: { d: 3.00, r: -3.50 }, 4: { d: 3.50, r: -4.00 }, 5: { d: 6.00, r: -3.00 }, 6: { d: 6.50, r: 0.00 } },
15
- 2: { 1: { d: 6.00, r: 3.00 }, 2: { d: 3.00, r: 4.00 }, 3: { d: 0.50, r: 0.50 }, 4: { d: 6.00, r: -3.00 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 1.25, r: 0.75 } },
16
- 3: { 1: { d: 6.00, r: 3.00 }, 2: { d: 3.00, r: 4.00 }, 3: { d: 6.00, r: -3.00 }, 4: { d: 0.95, r: -4.00 }, 5: { d: 1.00, r: -1.00 }, 6: { d: 6.50, r: 0.00 } },
17
- 4: { 1: { d: 8.50, r: 4.00 }, 2: { d: 6.00, r: -3.00 }, 3: { d: 1.25, r: -4.00 }, 4: { d: 0.75, r: -4.05 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 6.00, r: 3.00 } },
18
- 5: { 1: { d: 6.00, r: 3.00 }, 2: { d: 2.50, r: 4.00 }, 3: { d: 1.00, r: 1.50 }, 4: { d: 6.00, r: -3.00 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 8.50, r: 1.50 } },
19
- 6: { 1: { d: 6.00, r: 3.00 }, 2: { d: 1.00, r: 1.50 }, 3: { d: 6.00, r: -3.00 }, 4: { d: 3.00, r: -4.00 }, 5: { d: 8.50, r: -1.50 }, 6: { d: 6.50, r: 0.00 } }
15
+ 1: { 1: { d: 6.5, r: 3.5 }, 2: { d: 6, r: 3 }, 3: { d: 3, r: -3.5 }, 4: { d: 3.5, r: -4 }, 5: { d: 6, r: -3 }, 6: { d: 6.5, r: 0 } },
16
+ 2: { 1: { d: 5.65, r: 2.3 }, 2: { d: 0.65, r: 2.1 }, 3: { d: 6, r: -2.3 }, 4: { d: 2.75, r: -3.9 }, 5: { d: 7.85, r: -1.7 }, 6: { d: 6.75, r: 0.1 } },
17
+ 3: { 1: { d: 6, r: 3 }, 2: { d: 2.5, r: 3.95 }, 3: { d: 0.75, r: 1 }, 4: { d: 5.55, r: -2.75 }, 5: { d: 6.1, r: 0.1 }, 6: { d: 7.8, r: 1.65 } },
18
+ 4: { 1: { d: 8.5, r: 4 }, 2: { d: 6, r: -3 }, 3: { d: 1.25, r: -4 }, 4: { d: 0.75, r: -4.05 }, 5: { d: 6.5, r: 0 }, 6: { d: 6, r: 3 } },
19
+ 5: { 1: { d: 6.1, r: 2.6 }, 2: { d: 3.25, r: 3.9 }, 3: { d: 5.8, r: -2.75 }, 4: { d: 0.75, r: -3.85 }, 5: { d: 1.9, r: -1.7 }, 6: { d: 6.75, r: -0.1 } },
20
+ 6: { 1: { d: 6, r: 3 }, 2: { d: 2.6, r: 3.85 }, 3: { d: 0.5, r: 0.4 }, 4: { d: 5.9, r: -2.9 }, 5: { d: 6.55, r: 0 }, 6: { d: 1.6, r: 0.9 } }
20
21
  },
21
22
  DEFENCE: {
22
- 1: { 1: { d: 5.00, r: 3.00 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -3.00 } },
23
- 2: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -3.00 }, 6: { d: 5.00, r: 3.00 } },
24
- 3: { 1: { d: 5.00, r: -3.00 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 3.00 }, 6: { d: 7.00, r: 0.00 } },
25
- 4: { 1: { d: 5.00, r: 3.00 }, 2: { d: 0.50, r: -2.50 }, 3: { d: 0.50, r: 0.00 }, 4: { d: 0.50, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -3.00 } },
26
- 5: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.50, r: 0.00 }, 3: { d: 0.50, r: 2.50 }, 4: { d: 0.50, r: -2.50 }, 5: { d: 5.00, r: -3.00 }, 6: { d: 5.00, r: 3.00 } },
27
- 6: { 1: { d: 5.00, r: -3.00 }, 2: { d: 0.50, r: 2.50 }, 3: { d: 0.50, r: -2.50 }, 4: { d: 0.50, r: 0.00 }, 5: { d: 5.00, r: 3.00 }, 6: { d: 7.00, r: 0.00 } }
23
+ 1: { 1: { d: 5, r: 3 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -3 } },
24
+ 2: { 1: { d: 4.9, r: -3 }, 2: { d: 0.6, r: 2.65 }, 3: { d: 0.65, r: -3 }, 4: { d: 0.65, r: -0.1 }, 5: { d: 5, r: 3.05 }, 6: { d: 6.75, r: 0.2 } },
25
+ 3: { 1: { d: 7, r: 0.05 }, 2: { d: 0.5, r: 0.2 }, 3: { d: 0.6, r: 2.65 }, 4: { d: 0.5, r: -2.7 }, 5: { d: 4.7, r: -2.3 }, 6: { d: 4.85, r: 2.6 } },
26
+ 4: { 1: { d: 5, r: 3 }, 2: { d: 0.5, r: -2.5 }, 3: { d: 0.5, r: 0 }, 4: { d: 0.5, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -3 } },
27
+ 5: { 1: { d: 4.8, r: -3.15 }, 2: { d: 0.6, r: 2.5 }, 3: { d: 0.65, r: -2.85 }, 4: { d: 0.65, r: -0.15 }, 5: { d: 5, r: 2.75 }, 6: { d: 6.75, r: 0.05 } },
28
+ 6: { 1: { d: 7.2, r: -0.05 }, 2: { d: 0.45, r: -0.4 }, 3: { d: 0.55, r: 2.45 }, 4: { d: 0.55, r: -3 }, 5: { d: 4.85, r: -2.85 }, 6: { d: 4.8, r: 2.25 } }
28
29
  },
29
30
  DEF_L: {
30
- 1: { 1: { d: 5.00, r: 1.50 }, 2: { d: 0.25, r: -4.00 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8.00, r: -0.50 }, 6: { d: 5.00, r: -4.20 } },
31
- 2: { 1: { d: 8.00, r: -0.50 }, 2: { d: 0.25, r: -3.25 }, 3: { d: 1.75, r: 1.25 }, 4: { d: 0.25, r: -4.00 }, 5: { d: 5.00, r: -4.20 }, 6: { d: 5.00, r: 1.50 } },
32
- 3: { 1: { d: 5.00, r: -4.20 }, 2: { d: 1.75, r: 1.25 }, 3: { d: 0.25, r: -4.00 }, 4: { d: 0.25, r: -3.25 }, 5: { d: 5.00, r: 1.50 }, 6: { d: 8.00, r: -0.50 } },
33
- 4: { 1: { d: 5.00, r: 1.50 }, 2: { d: 0.25, r: -4.00 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8.00, r: -0.50 }, 6: { d: 5.00, r: -4.20 } },
34
- 5: { 1: { d: 8.00, r: -0.50 }, 2: { d: 0.25, r: -3.25 }, 3: { d: 1.75, r: 1.25 }, 4: { d: 0.25, r: -4.00 }, 5: { d: 5.00, r: -4.20 }, 6: { d: 5.00, r: 1.50 } },
35
- 6: { 1: { d: 5.00, r: -4.20 }, 2: { d: 1.75, r: 1.25 }, 3: { d: 0.25, r: -4.00 }, 4: { d: 0.25, r: -3.25 }, 5: { d: 5.00, r: 1.50 }, 6: { d: 8.00, r: -0.50 } }
31
+ 1: { 1: { d: 5, r: 1.5 }, 2: { d: 0.25, r: -4 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8, r: -0.5 }, 6: { d: 5, r: -4.2 } },
32
+ 2: { 1: { d: 4.45, r: -3.95 }, 2: { d: 1.9, r: 1.3 }, 3: { d: 0.4, r: -3.8 }, 4: { d: 0.4, r: -2.9 }, 5: { d: 5.05, r: 2.45 }, 6: { d: 7.6, r: -0.05 } },
33
+ 3: { 1: { d: 8.2, r: -0.7 }, 2: { d: 0.4, r: -2.65 }, 3: { d: 2.1, r: 0.8 }, 4: { d: 0.45, r: -3.8 }, 5: { d: 5.1, r: -3.85 }, 6: { d: 5.2, r: 1.8 } },
34
+ 4: { 1: { d: 5, r: 1.5 }, 2: { d: 0.25, r: -4 }, 3: { d: 0.25, r: -3.25 }, 4: { d: 1.75, r: 1.25 }, 5: { d: 8, r: -0.5 }, 6: { d: 5, r: -4.2 } },
35
+ 5: { 1: { d: 5.05, r: -3.9 }, 2: { d: 2.2, r: 0.65 }, 3: { d: 0.65, r: -3.8 }, 4: { d: 0.65, r: -2.75 }, 5: { d: 4.65, r: 1.1 }, 6: { d: 7.7, r: -0.75 } },
36
+ 6: { 1: { d: 7.15, r: 0.25 }, 2: { d: 0.5, r: -2.7 }, 3: { d: 1.8, r: 1.1 }, 4: { d: 0.5, r: -3.8 }, 5: { d: 4.75, r: -3.85 }, 6: { d: 4.95, r: 1.6 } }
36
37
  },
37
38
  DEF_M: {
38
- 1: { 1: { d: 5.00, r: 2.50 }, 2: { d: 1.75, r: -2.50 }, 3: { d: 0.25, r: 0.00 }, 4: { d: 1.75, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
39
- 2: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.25, r: 0.00 }, 3: { d: 1.75, r: 2.50 }, 4: { d: 1.75, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
40
- 3: { 1: { d: 5.00, r: -2.50 }, 2: { d: 1.75, r: 2.50 }, 3: { d: 1.75, r: -2.50 }, 4: { d: 0.25, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 7.00, r: 0.00 } },
41
- 4: { 1: { d: 5.00, r: 2.50 }, 2: { d: 1.75, r: -2.50 }, 3: { d: 0.25, r: 0.00 }, 4: { d: 1.75, r: 2.50 }, 5: { d: 7.00, r: 0.00 }, 6: { d: 5.00, r: -2.50 } },
42
- 5: { 1: { d: 7.00, r: 0.00 }, 2: { d: 0.25, r: 0.00 }, 3: { d: 1.75, r: 2.50 }, 4: { d: 1.75, r: -2.50 }, 5: { d: 5.00, r: -2.50 }, 6: { d: 5.00, r: 2.50 } },
43
- 6: { 1: { d: 5.00, r: -2.50 }, 2: { d: 1.75, r: 2.50 }, 3: { d: 1.75, r: -2.50 }, 4: { d: 0.25, r: 0.00 }, 5: { d: 5.00, r: 2.50 }, 6: { d: 7.00, r: 0.00 } }
39
+ 1: { 1: { d: 5, r: 2.5 }, 2: { d: 1.75, r: -2.5 }, 3: { d: 0.25, r: 0 }, 4: { d: 1.75, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -2.5 } },
40
+ 2: { 1: { d: 5, r: -2.8 }, 2: { d: 1.85, r: 2.5 }, 3: { d: 1.85, r: -2.4 }, 4: { d: 0.4, r: 0.15 }, 5: { d: 5, r: 2.65 }, 6: { d: 7, r: 0.05 } },
41
+ 3: { 1: { d: 7.15, r: 0.1 }, 2: { d: 0.5, r: 0.1 }, 3: { d: 1.95, r: 2.45 }, 4: { d: 1.8, r: -2.55 }, 5: { d: 5.25, r: -2.45 }, 6: { d: 5.2, r: 2.8 } },
42
+ 4: { 1: { d: 5, r: 2.5 }, 2: { d: 1.75, r: -2.5 }, 3: { d: 0.25, r: 0 }, 4: { d: 1.75, r: 2.5 }, 5: { d: 7, r: 0 }, 6: { d: 5, r: -2.5 } },
43
+ 5: { 1: { d: 4.9, r: -2.35 }, 2: { d: 1.95, r: 2.4 }, 3: { d: 1.85, r: -2.6 }, 4: { d: 0.55, r: -0.2 }, 5: { d: 4.9, r: 2.45 }, 6: { d: 6.7, r: -0.1 } },
44
+ 6: { 1: { d: 7.35, r: 0.05 }, 2: { d: 0.6, r: 0.1 }, 3: { d: 2, r: 2.45 }, 4: { d: 2.25, r: -1.95 }, 5: { d: 5.2, r: -2.05 }, 6: { d: 5.3, r: 2.5 } }
44
45
  },
45
46
  DEF_R: {
46
- 1: { 1: { d: 5.00, r: 4.20 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4.00 }, 5: { d: 8.00, r: 0.50 }, 6: { d: 5.00, r: -1.50 } },
47
- 2: { 1: { d: 8.00, r: 0.50 }, 2: { d: 0.25, r: 3.25 }, 3: { d: 0.25, r: 4.00 }, 4: { d: 1.75, r: -1.25 }, 5: { d: 5.00, r: -1.50 }, 6: { d: 5.00, r: 4.20 } },
48
- 3: { 1: { d: 5.00, r: -1.50 }, 2: { d: 0.25, r: 4.00 }, 3: { d: 1.75, r: -1.25 }, 4: { d: 0.25, r: 3.25 }, 5: { d: 5.00, r: 4.20 }, 6: { d: 8.00, r: 0.50 } },
49
- 4: { 1: { d: 5.00, r: 4.20 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4.00 }, 5: { d: 8.00, r: 0.50 }, 6: { d: 5.00, r: -1.50 } },
50
- 5: { 1: { d: 8.00, r: 0.50 }, 2: { d: 0.25, r: 3.25 }, 3: { d: 0.25, r: 4.00 }, 4: { d: 1.75, r: -1.25 }, 5: { d: 5.00, r: -1.50 }, 6: { d: 5.00, r: 4.20 } },
51
- 6: { 1: { d: 5.00, r: -1.50 }, 2: { d: 0.25, r: 4.00 }, 3: { d: 1.75, r: -1.25 }, 4: { d: 0.25, r: 3.25 }, 5: { d: 5.00, r: 4.20 }, 6: { d: 8.00, r: 0.50 } }
47
+ 1: { 1: { d: 5, r: 4.2 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4 }, 5: { d: 8, r: 0.5 }, 6: { d: 5, r: -1.5 } },
48
+ 2: { 1: { d: 4.65, r: -1 }, 2: { d: 0.25, r: 3.85 }, 3: { d: 1.75, r: -1.4 }, 4: { d: 0.3, r: 2.95 }, 5: { d: 4.3, r: 3.95 }, 6: { d: 8.15, r: 0.5 } },
49
+ 3: { 1: { d: 8.05, r: 0.4 }, 2: { d: 0.4, r: 2.95 }, 3: { d: 0.4, r: 3.85 }, 4: { d: 2, r: -2 }, 5: { d: 4.65, r: -1.15 }, 6: { d: 4.75, r: 4 } },
50
+ 4: { 1: { d: 5, r: 4.2 }, 2: { d: 1.75, r: -1.25 }, 3: { d: 0.25, r: 3.25 }, 4: { d: 0.25, r: 4 }, 5: { d: 8, r: 0.5 }, 6: { d: 5, r: -1.5 } },
51
+ 5: { 1: { d: 5.35, r: -2 }, 2: { d: 0.5, r: 3.65 }, 3: { d: 2.1, r: -1.25 }, 4: { d: 0.5, r: 2.6 }, 5: { d: 5.4, r: 3.85 }, 6: { d: 7.75, r: -0.15 } },
52
+ 6: { 1: { d: 7.8, r: 0.75 }, 2: { d: 0.45, r: 2.9 }, 3: { d: 0.45, r: 3.95 }, 4: { d: 1.75, r: -0.25 }, 5: { d: 5.15, r: -1.4 }, 6: { d: 4.9, r: 4 } }
52
53
  },
53
54
  ATTACK: {
54
- 1: { 1: { d: 0.50, r: 1.50 }, 2: { d: 3.75, r: -5.00 }, 3: { d: 3.00, r: 0.25 }, 4: { d: 3.75, r: 5.00 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 4.50, r: -2.50 } },
55
- 2: { 1: { d: 6.50, r: 0.00 }, 2: { d: 3.00, r: 0.25 }, 3: { d: 3.75, r: 5.00 }, 4: { d: 3.75, r: -5.00 }, 5: { d: 4.50, r: -2.50 }, 6: { d: 0.50, r: 1.50 } },
56
- 3: { 1: { d: 4.50, r: -2.50 }, 2: { d: 3.75, r: 5.00 }, 3: { d: 3.75, r: -5.00 }, 4: { d: 3.00, r: 0.25 }, 5: { d: 0.50, r: 1.50 }, 6: { d: 6.50, r: 0.00 } },
57
- 4: { 1: { d: 6.50, r: 4.90 }, 2: { d: 3.75, r: -5.00 }, 3: { d: 3.00, r: 0.25 }, 4: { d: 0.50, r: 1.50 }, 5: { d: 6.50, r: 0.00 }, 6: { d: 4.50, r: -2.50 } },
58
- 5: { 1: { d: 6.50, r: 0.00 }, 2: { d: 3.00, r: 0.25 }, 3: { d: 0.50, r: 1.50 }, 4: { d: 3.75, r: -5.00 }, 5: { d: 4.50, r: -2.50 }, 6: { d: 6.50, r: 4.90 } },
59
- 6: { 1: { d: 4.50, r: -2.50 }, 2: { d: 0.50, r: 1.50 }, 3: { d: 3.75, r: -5.00 }, 4: { d: 3.00, r: 0.25 }, 5: { d: 6.50, r: 4.90 }, 6: { d: 6.50, r: 0.00 } }
55
+ 1: { 1: { d: 0.5, r: 1.5 }, 2: { d: 3.75, r: -5 }, 3: { d: 3, r: 0.25 }, 4: { d: 3.75, r: 5 }, 5: { d: 6.5, r: 0 }, 6: { d: 4.5, r: -2.5 } },
56
+ 2: { 1: { d: 5.1, r: -2 }, 2: { d: 0.45, r: 1.55 }, 3: { d: 3.6, r: -5.2 }, 4: { d: 2.8, r: 0.2 }, 5: { d: 6.4, r: 5.05 }, 6: { d: 6.55, r: -0.6 } },
57
+ 3: { 1: { d: 6.5, r: -0.15 }, 2: { d: 3, r: 0.35 }, 3: { d: 0.5, r: 1.6 }, 4: { d: 2.4, r: -5.15 }, 5: { d: 4.6, r: -2.55 }, 6: { d: 5.4, r: 5.2 } },
58
+ 4: { 1: { d: 6.5, r: 4.9 }, 2: { d: 3.75, r: -5 }, 3: { d: 3, r: 0.25 }, 4: { d: 0.5, r: 1.5 }, 5: { d: 6.5, r: 0 }, 6: { d: 4.5, r: -2.5 } },
59
+ 5: { 1: { d: 4.65, r: -2.35 }, 2: { d: 3.65, r: 4.8 }, 3: { d: 2.9, r: -5.15 }, 4: { d: 3.05, r: 0.4 }, 5: { d: 0.75, r: 1.7 }, 6: { d: 6.4, r: -0.05 } },
60
+ 6: { 1: { d: 6.2, r: -0.4 }, 2: { d: 3, r: 0.2 }, 3: { d: 3.65, r: 5.2 }, 4: { d: 3.55, r: -5.2 }, 5: { d: 4.5, r: -2.45 }, 6: { d: 0.65, r: 1.3 } }
60
61
  },
61
62
  ATK_L: {
62
- 1: { 1: { d: 0.75, r: 0.00 }, 2: { d: 0.50, r: -4.00 }, 3: { d: 1.00, r: -2.50 }, 4: { d: 3.50, r: 0.75 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.50, r: -4.00 } },
63
- 2: { 1: { d: 6.25, r: -0.75 }, 2: { d: 1.00, r: -2.50 }, 3: { d: 3.50, r: 0.75 }, 4: { d: 0.50, r: -4.00 }, 5: { d: 3.50, r: -4.00 }, 6: { d: 0.75, r: 0.00 } },
64
- 3: { 1: { d: 3.50, r: -4.00 }, 2: { d: 3.50, r: 0.75 }, 3: { d: 0.50, r: -4.00 }, 4: { d: 1.00, r: -2.50 }, 5: { d: 0.75, r: 0.00 }, 6: { d: 6.25, r: -0.75 } },
65
- 4: { 1: { d: 3.50, r: 0.75 }, 2: { d: 0.50, r: -4.00 }, 3: { d: 1.00, r: -2.50 }, 4: { d: 0.75, r: 0.00 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.50, r: -4.00 } },
66
- 5: { 1: { d: 6.25, r: -0.75 }, 2: { d: 1.00, r: -2.50 }, 3: { d: 0.75, r: 0.00 }, 4: { d: 0.50, r: -4.00 }, 5: { d: 3.50, r: -4.00 }, 6: { d: 3.50, r: 0.75 } },
67
- 6: { 1: { d: 3.50, r: -4.00 }, 2: { d: 0.75, r: 0.00 }, 3: { d: 0.50, r: -4.00 }, 4: { d: 1.00, r: -2.50 }, 5: { d: 3.50, r: 0.75 }, 6: { d: 6.25, r: -0.75 } }
63
+ 1: { 1: { d: 0.75, r: 0 }, 2: { d: 0.5, r: -4 }, 3: { d: 1, r: -2.5 }, 4: { d: 3.5, r: 0.75 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.5, r: -4 } },
64
+ 2: { 1: { d: 3.4, r: -4.05 }, 2: { d: 0.75, r: 0 }, 3: { d: 0.9, r: -4.15 }, 4: { d: 1.8, r: -2.5 }, 5: { d: 3.4, r: 0.5 }, 6: { d: 6.5, r: -1.15 } },
65
+ 3: { 1: { d: 6.35, r: -0.1 }, 2: { d: 2.1, r: -2.45 }, 3: { d: 0.9, r: 0 }, 4: { d: 0.8, r: -3.95 }, 5: { d: 4.6, r: -3.75 }, 6: { d: 3.6, r: 1.45 } },
66
+ 4: { 1: { d: 3.5, r: 0.75 }, 2: { d: 0.5, r: -4 }, 3: { d: 1, r: -2.5 }, 4: { d: 0.75, r: 0 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.5, r: -4 } },
67
+ 5: { 1: { d: 4.25, r: -3.85 }, 2: { d: 3.55, r: 0.75 }, 3: { d: 1, r: -4.1 }, 4: { d: 2.05, r: -2.65 }, 5: { d: 0.85, r: -0.15 }, 6: { d: 6, r: -0.8 } },
68
+ 6: { 1: { d: 5.9, r: -1 }, 2: { d: 1.05, r: -2.5 }, 3: { d: 3.45, r: 0.9 }, 4: { d: 0.7, r: -3.9 }, 5: { d: 3.4, r: -4.05 }, 6: { d: 0.75, r: -0.2 } }
68
69
  },
69
70
  ATK_M: {
70
- 1: { 1: { d: 0.75, r: 1.25 }, 2: { d: 1.25, r: -2.00 }, 3: { d: 0.75, r: 0.50 }, 4: { d: 2.25, r: 2.60 }, 5: { d: 6.50, r: 1.50 }, 6: { d: 4.00, r: -1.50 } },
71
- 2: { 1: { d: 6.50, r: 1.50 }, 2: { d: 0.75, r: 0.50 }, 3: { d: 2.25, r: 2.60 }, 4: { d: 1.25, r: -2.00 }, 5: { d: 4.00, r: -1.50 }, 6: { d: 0.75, r: 1.25 } },
72
- 3: { 1: { d: 4.00, r: -1.50 }, 2: { d: 2.25, r: 2.60 }, 3: { d: 1.25, r: -2.00 }, 4: { d: 0.75, r: 0.50 }, 5: { d: 0.75, r: 1.25 }, 6: { d: 6.50, r: 1.50 } },
73
- 4: { 1: { d: 2.25, r: 2.60 }, 2: { d: 1.25, r: -2.00 }, 3: { d: 0.75, r: 0.50 }, 4: { d: 0.75, r: 1.25 }, 5: { d: 6.50, r: 1.50 }, 6: { d: 4.00, r: -1.50 } },
74
- 5: { 1: { d: 6.50, r: 1.50 }, 2: { d: 0.75, r: 0.50 }, 3: { d: 0.75, r: 1.25 }, 4: { d: 1.25, r: -2.00 }, 5: { d: 4.00, r: -1.50 }, 6: { d: 2.25, r: 2.60 } },
75
- 6: { 1: { d: 4.00, r: -1.50 }, 2: { d: 0.75, r: 1.25 }, 3: { d: 1.25, r: -2.00 }, 4: { d: 0.75, r: 0.50 }, 5: { d: 2.25, r: 2.60 }, 6: { d: 6.50, r: 1.50 } }
71
+ 1: { 1: { d: 0.75, r: 1.25 }, 2: { d: 1.25, r: -2 }, 3: { d: 0.75, r: 0.5 }, 4: { d: 2.25, r: 2.6 }, 5: { d: 6.5, r: 1.5 }, 6: { d: 4, r: -1.5 } },
72
+ 2: { 1: { d: 4.5, r: -2.2 }, 2: { d: 0.7, r: 1.25 }, 3: { d: 1.8, r: -2.45 }, 4: { d: 0.9, r: 0.05 }, 5: { d: 2.75, r: 3.05 }, 6: { d: 5.75, r: 0 } },
73
+ 3: { 1: { d: 6.55, r: 1.15 }, 2: { d: 0.9, r: 0.3 }, 3: { d: 0.85, r: 1.45 }, 4: { d: 1.7, r: -2.7 }, 5: { d: 3.95, r: -1.75 }, 6: { d: 2.25, r: 3.2 } },
74
+ 4: { 1: { d: 2.25, r: 2.6 }, 2: { d: 1.25, r: -2 }, 3: { d: 0.75, r: 0.5 }, 4: { d: 0.75, r: 1.25 }, 5: { d: 6.5, r: 1.5 }, 6: { d: 4, r: -1.5 } },
75
+ 5: { 1: { d: 4.35, r: -1.5 }, 2: { d: 2.25, r: 2.85 }, 3: { d: 1.9, r: -2.55 }, 4: { d: 0.8, r: 0.35 }, 5: { d: 0.6, r: 1.45 }, 6: { d: 5.55, r: 1.45 } },
76
+ 6: { 1: { d: 5.2, r: 1.1 }, 2: { d: 0.8, r: 0.35 }, 3: { d: 2.4, r: 3 }, 4: { d: 1.8, r: -2.15 }, 5: { d: 4.5, r: -1.7 }, 6: { d: 0.8, r: 1.35 } }
76
77
  },
77
78
  ATK_R: {
78
- 1: { 1: { d: 1.75, r: 2.50 }, 2: { d: 1.50, r: -1.75 }, 3: { d: 0.75, r: 1.75 }, 4: { d: 0.50, r: 4.00 }, 5: { d: 5.00, r: 3.25 }, 6: { d: 5.75, r: -2.00 } },
79
- 2: { 1: { d: 5.00, r: 3.25 }, 2: { d: 0.75, r: 1.75 }, 3: { d: 0.50, r: 4.00 }, 4: { d: 1.50, r: -1.75 }, 5: { d: 5.75, r: -2.00 }, 6: { d: 1.75, r: 2.50 } },
80
- 3: { 1: { d: 5.75, r: -2.00 }, 2: { d: 0.50, r: 4.00 }, 3: { d: 1.50, r: -1.75 }, 4: { d: 0.75, r: 1.75 }, 5: { d: 1.75, r: 2.50 }, 6: { d: 5.00, r: 3.25 } },
81
- 4: { 1: { d: 2.25, r: 4.00 }, 2: { d: 2.25, r: -1.75 }, 3: { d: 0.75, r: 1.50 }, 4: { d: 1.50, r: 2.25 }, 5: { d: 6.00, r: 2.25 }, 6: { d: 5.00, r: -0.75 } },
82
- 5: { 1: { d: 6.00, r: 2.25 }, 2: { d: 0.75, r: 1.50 }, 3: { d: 1.50, r: 2.25 }, 4: { d: 2.25, r: -1.75 }, 5: { d: 5.00, r: -0.75 }, 6: { d: 2.25, r: 4.00 } },
83
- 6: { 1: { d: 5.00, r: -0.75 }, 2: { d: 1.50, r: 2.25 }, 3: { d: 2.25, r: -1.75 }, 4: { d: 0.75, r: 1.50 }, 5: { d: 2.25, r: 4.00 }, 6: { d: 6.00, r: 2.25 } }
79
+ 1: { 1: { d: 1.75, r: 2.5 }, 2: { d: 1.5, r: -1.75 }, 3: { d: 0.75, r: 1.75 }, 4: { d: 0.5, r: 4 }, 5: { d: 5, r: 3.25 }, 6: { d: 5.75, r: -2 } },
80
+ 2: { 1: { d: 4.65, r: -0.8 }, 2: { d: 0.75, r: 1.75 }, 3: { d: 1.85, r: -1.75 }, 4: { d: 1.7, r: 2.2 }, 5: { d: 2.15, r: 4.25 }, 6: { d: 6.25, r: 2 } },
81
+ 3: { 1: { d: 5.1, r: 3.15 }, 2: { d: 1.85, r: 2.6 }, 3: { d: 0.8, r: 1.75 }, 4: { d: 2.15, r: -1.7 }, 5: { d: 4.9, r: -1.25 }, 6: { d: 1.9, r: 4.15 } },
82
+ 4: { 1: { d: 2.25, r: 4 }, 2: { d: 2.25, r: -1.75 }, 3: { d: 0.75, r: 1.5 }, 4: { d: 1.5, r: 2.25 }, 5: { d: 6, r: 2.25 }, 6: { d: 5, r: -0.75 } },
83
+ 5: { 1: { d: 5.95, r: -2 }, 2: { d: 0.9, r: 3.7 }, 3: { d: 2.2, r: -1.6 }, 4: { d: 2, r: 2.35 }, 5: { d: 0.9, r: 1.15 }, 6: { d: 6, r: 1.9 } },
84
+ 6: { 1: { d: 5.35, r: 2.35 }, 2: { d: 2.05, r: 2.1 }, 3: { d: 0.8, r: 4 }, 4: { d: 2.1, r: -1.95 }, 5: { d: 4.9, r: -1.4 }, 6: { d: 0.4, r: 1.3 } }
84
85
  }
85
86
  };
86
87
  // The default coordinate table as a BaseConfig.coords (jsonb string keys). Shared, readonly; materialized (and so
@@ -97,36 +98,47 @@ const DEFAULT_COORDS = (() => {
97
98
  }
98
99
  return out;
99
100
  })();
100
- // The owner's authored per-point-of-attack block map for the 5-1 (owner 2026-08-07), keyed
101
+ // The owner's corrected per-point-of-attack block map for the 5-1 (exported 2026-08-09), keyed
101
102
  // [DEF_L|DEF_M|DEF_R][rotation][zone] -> canBlock. `false` = that front-row zone sits OUT of the block for an attack
102
- // from that side; `true` = reads/joins the wall. Only front-row zones (2/3/4) are tagged. Same rotation convention
103
- // as DEFAULT_COORDS. Generated from the finalized 5-1 sr-mapper preset's Def L/M/R block/noblock tags.
103
+ // from that side; `true` = reads/joins the wall. Only the front-row zones in play for the rotation are tagged. Same
104
+ // rotation convention as DEFAULT_COORDS.
104
105
  const DEFAULT_BLOCKING = {
105
106
  DEF_L: {
106
107
  1: { 2: true, 3: true, 4: false },
107
- 2: { 2: true, 3: false, 4: true },
108
- 3: { 2: false, 3: true, 4: true },
108
+ 2: { 2: false, 4: true },
109
+ 3: { 3: false, 4: true },
109
110
  4: { 2: true, 3: true, 4: false },
110
- 5: { 2: true, 3: false, 4: true },
111
- 6: { 2: false, 3: true, 4: true }
111
+ 5: { 2: false, 4: true },
112
+ 6: { 3: false, 4: true }
112
113
  },
113
114
  DEF_M: {
114
115
  1: { 2: false, 3: true, 4: false },
115
- 2: { 2: true, 3: false, 4: false },
116
- 3: { 2: false, 3: false, 4: true },
116
+ 2: { 2: false, 3: false },
117
+ 3: { 3: false, 4: false },
117
118
  4: { 2: false, 3: true, 4: false },
118
- 5: { 2: true, 3: false, 4: false },
119
- 6: { 2: false, 3: false, 4: true }
119
+ 5: { 2: false, 3: false },
120
+ 6: { 3: false, 4: false }
120
121
  },
121
122
  DEF_R: {
122
123
  1: { 2: false, 3: true, 4: true },
123
- 2: { 2: true, 3: true, 4: false },
124
- 3: { 2: true, 3: false, 4: true },
124
+ 2: { 2: true, 3: false },
125
+ 3: { 2: true, 4: false },
125
126
  4: { 2: false, 3: true, 4: true },
126
- 5: { 2: true, 3: true, 4: false },
127
- 6: { 2: true, 3: false, 4: true }
127
+ 5: { 2: true, 3: false },
128
+ 6: { 2: true, 4: false }
128
129
  }
129
130
  };
131
+ // The owner's corrected 5-1 serve-receive participation map (exported 2026-08-09). The 5-1 uses this exact map; the
132
+ // other systems derive their 3-passer map from slot functions (defaultReceiveMap) since their receiving personnel
133
+ // differ. Keyed [rotation][zone] -> passes.
134
+ const DEFAULT_5_1_RECEIVE = {
135
+ 1: { 1: false, 2: true, 3: false, 4: false, 5: true, 6: true },
136
+ 2: { 1: true, 2: false, 3: true, 4: false, 5: false, 6: true },
137
+ 3: { 1: true, 2: false, 3: false, 4: true, 5: true, 6: false },
138
+ 4: { 1: false, 2: true, 3: false, 4: false, 5: true, 6: true },
139
+ 5: { 1: true, 2: false, 3: true, 4: false, 5: false, 6: true },
140
+ 6: { 1: true, 2: false, 3: false, 4: true, 5: true, 6: false }
141
+ };
130
142
  // Rotation index -> the setter's rotational zone (inverse of SETTER_ZONE_TO_ROTATION {1:1,6:2,5:3,4:4,3:5,2:6}).
131
143
  const ROTATION_TO_SETTER_ZONE = { 1: 1, 2: 6, 3: 5, 4: 4, 5: 3, 6: 2 };
132
144
  // The default serve-receive participation map: the standard 3-passer formation. A rotational slot passes iff its
@@ -147,8 +159,9 @@ export function defaultReceiveMap(system) {
147
159
  return receive;
148
160
  }
149
161
  // The default base config a team of the given system starts with. Every team always has one (materialized on team
150
- // creation and by the backfill migration); the coordinates are the same 5-1 table for every system, only the
151
- // receive map is derived per system.
162
+ // creation and by the backfill migration). Every system reuses the corrected 5-1 coordinate table and block map; the
163
+ // 5-1 uses the owner's exported receive map, the other systems derive their receive map per system.
152
164
  export function defaultBaseConfig(system) {
153
- return { coords: DEFAULT_COORDS, receive: defaultReceiveMap(system), blocking: DEFAULT_BLOCKING };
165
+ const receive = system === RotationSystemEnum.FIVE_ONE ? DEFAULT_5_1_RECEIVE : defaultReceiveMap(system);
166
+ return { coords: DEFAULT_COORDS, receive, blocking: DEFAULT_BLOCKING };
154
167
  }
@@ -4,6 +4,7 @@ export * from './formation';
4
4
  export * from './tactics';
5
5
  export * from './base-config';
6
6
  export * from './default-base-config';
7
+ export * from './receive-overlap';
7
8
  export * from './team-name';
8
9
  export * from './energy-band';
9
10
  export * from './pinch-condition';
@@ -4,6 +4,7 @@ export * from './formation';
4
4
  export * from './tactics';
5
5
  export * from './base-config';
6
6
  export * from './default-base-config';
7
+ export * from './receive-overlap';
7
8
  export * from './team-name';
8
9
  export * from './energy-band';
9
10
  export * from './pinch-condition';
@@ -0,0 +1,33 @@
1
+ import { BaseConfig } from './base-config';
2
+ export interface ReceiveOverlapViolation {
3
+ /** Rotation (1..6) that has at least one violation. */
4
+ readonly rotation: number;
5
+ /** The rotational zones (1..6) involved in a violation, to flag in the editor. */
6
+ readonly zones: number[];
7
+ /** Human-readable violation messages for that rotation. */
8
+ readonly messages: string[];
9
+ }
10
+ /**
11
+ * Returns every RECEIVE rotation that breaks the overlap rule (empty if the whole receive formation is legal).
12
+ * A missing RECEIVE map or a missing zone is skipped rather than flagged, so partial/legacy configs never throw.
13
+ */
14
+ export declare function receiveOverlapViolations(config: BaseConfig): ReceiveOverlapViolation[];
15
+ /** True when the RECEIVE formation of `config` respects the overlap rule in every rotation. */
16
+ export declare function isReceiveOverlapLegal(config: BaseConfig): boolean;
17
+ /**
18
+ * Returns every SERVE rotation whose server (zone 1) is NOT behind the end line (owner 2026-08-10: on Serve, only
19
+ * the server is constrained; the rest of the serving formation is free). A missing SERVE map or zone-1 coord is
20
+ * skipped rather than flagged, so partial/legacy configs never throw.
21
+ */
22
+ export declare function serveLineViolations(config: BaseConfig): ReceiveOverlapViolation[];
23
+ /** A base-config rule violation, tagged with the formation it belongs to so the editor/API can point at it. */
24
+ export interface FormationViolation extends ReceiveOverlapViolation {
25
+ readonly formation: 'RECEIVE' | 'SERVE';
26
+ }
27
+ /**
28
+ * Every base-config rule violation across the constrained formations: the RECEIVE overlap rule and the SERVE
29
+ * server-behind-the-line rule. This is the single check the tactics save (UI + API) and the editor flagging share.
30
+ */
31
+ export declare function baseConfigViolations(config: BaseConfig): FormationViolation[];
32
+ /** True when `config` breaks no RECEIVE overlap rule and no SERVE server-line rule. */
33
+ export declare function isBaseConfigLegal(config: BaseConfig): boolean;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Returns every RECEIVE rotation that breaks the overlap rule (empty if the whole receive formation is legal).
3
+ * A missing RECEIVE map or a missing zone is skipped rather than flagged, so partial/legacy configs never throw.
4
+ */
5
+ export function receiveOverlapViolations(config) {
6
+ const rc = config.coords?.RECEIVE;
7
+ if (rc == null)
8
+ return [];
9
+ const out = [];
10
+ for (let rot = 1; rot <= 6; rot++) {
11
+ const row = rc[String(rot)];
12
+ if (row == null)
13
+ continue;
14
+ const at = (zone) => row[String(zone)];
15
+ const bad = new Set();
16
+ const messages = [];
17
+ const lateral = (left, right, ln, rn) => {
18
+ const a = at(left);
19
+ const b = at(right);
20
+ if (a == null || b == null)
21
+ return;
22
+ if (a.r >= b.r) {
23
+ bad.add(left);
24
+ bad.add(right);
25
+ messages.push(`${ln} must be left of ${rn}`);
26
+ }
27
+ };
28
+ const depth = (front, back, fn, bn) => {
29
+ const a = at(front);
30
+ const b = at(back);
31
+ if (a == null || b == null)
32
+ return;
33
+ if (a.d >= b.d) {
34
+ bad.add(front);
35
+ bad.add(back);
36
+ messages.push(`${fn} must be in front of ${bn}`);
37
+ }
38
+ };
39
+ lateral(4, 3, 'left-front', 'middle-front');
40
+ lateral(3, 2, 'middle-front', 'right-front');
41
+ lateral(5, 6, 'left-back', 'middle-back');
42
+ lateral(6, 1, 'middle-back', 'right-back');
43
+ depth(2, 1, 'right-front', 'right-back');
44
+ depth(3, 6, 'middle-front', 'middle-back');
45
+ depth(4, 5, 'left-front', 'left-back');
46
+ if (bad.size > 0)
47
+ out.push({ rotation: rot, zones: [...bad].sort((a, b) => a - b), messages });
48
+ }
49
+ return out;
50
+ }
51
+ /** True when the RECEIVE formation of `config` respects the overlap rule in every rotation. */
52
+ export function isReceiveOverlapLegal(config) {
53
+ return receiveOverlapViolations(config).length === 0;
54
+ }
55
+ // The end line sits 9 m off the net (the FIVB court depth; matches the court editor's END_LINE). A server must
56
+ // contact the ball from BEHIND it, so on the SERVE formation the server (rotational zone 1) must have d >= this.
57
+ const END_LINE_DEPTH = 9;
58
+ /**
59
+ * Returns every SERVE rotation whose server (zone 1) is NOT behind the end line (owner 2026-08-10: on Serve, only
60
+ * the server is constrained; the rest of the serving formation is free). A missing SERVE map or zone-1 coord is
61
+ * skipped rather than flagged, so partial/legacy configs never throw.
62
+ */
63
+ export function serveLineViolations(config) {
64
+ const sc = config.coords?.SERVE;
65
+ if (sc == null)
66
+ return [];
67
+ const out = [];
68
+ for (let rot = 1; rot <= 6; rot++) {
69
+ const server = sc[String(rot)]?.['1'];
70
+ if (server == null)
71
+ continue;
72
+ if (server.d < END_LINE_DEPTH)
73
+ out.push({ rotation: rot, zones: [1], messages: ['server must be behind the end line'] });
74
+ }
75
+ return out;
76
+ }
77
+ /**
78
+ * Every base-config rule violation across the constrained formations: the RECEIVE overlap rule and the SERVE
79
+ * server-behind-the-line rule. This is the single check the tactics save (UI + API) and the editor flagging share.
80
+ */
81
+ export function baseConfigViolations(config) {
82
+ return [
83
+ ...receiveOverlapViolations(config).map(v => ({ ...v, formation: 'RECEIVE' })),
84
+ ...serveLineViolations(config).map(v => ({ ...v, formation: 'SERVE' }))
85
+ ];
86
+ }
87
+ /** True when `config` breaks no RECEIVE overlap rule and no SERVE server-line rule. */
88
+ export function isBaseConfigLegal(config) {
89
+ return baseConfigViolations(config).length === 0;
90
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.507",
3
+ "version": "0.0.509",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",