volleyballsimtypes 0.0.507 → 0.0.508

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.
@@ -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
+ }
@@ -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.508",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",