volleyballsimtypes 0.0.504 → 0.0.506
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/api/index.d.ts +3 -2
- package/dist/cjs/src/api/tactics-player-refs.js +2 -2
- package/dist/cjs/src/data/init-models.js +4 -0
- package/dist/cjs/src/data/models/base-position-preset.d.ts +22 -0
- package/dist/cjs/src/data/models/base-position-preset.js +54 -0
- package/dist/cjs/src/data/models/index.d.ts +1 -0
- package/dist/cjs/src/data/models/index.js +1 -0
- package/dist/cjs/src/data/models/tactics.d.ts +5 -3
- package/dist/cjs/src/data/models/tactics.js +4 -0
- package/dist/cjs/src/data/transformers/rally-event-injury.test.js +1 -1
- package/dist/cjs/src/data/transformers/rally-event-positional.test.js +10 -2
- package/dist/cjs/src/data/transformers/rally-event.js +3 -1
- package/dist/cjs/src/data/transformers/rally.test.js +2 -2
- package/dist/cjs/src/data/transformers/tactics.js +4 -0
- package/dist/cjs/src/data/transformers/tactics.test.js +34 -10
- package/dist/cjs/src/service/competition/competition-rewards.d.ts +20 -0
- package/dist/cjs/src/service/competition/competition-rewards.js +47 -0
- package/dist/cjs/src/service/competition/competition-rewards.test.d.ts +1 -0
- package/dist/cjs/src/service/competition/competition-rewards.test.js +32 -0
- package/dist/cjs/src/service/competition/index.d.ts +2 -0
- package/dist/cjs/src/service/competition/index.js +2 -0
- package/dist/cjs/src/service/competition/league-rewards.d.ts +21 -0
- package/dist/cjs/src/service/competition/league-rewards.js +58 -0
- package/dist/cjs/src/service/competition/league-rewards.test.d.ts +1 -0
- package/dist/cjs/src/service/competition/league-rewards.test.js +50 -0
- package/dist/cjs/src/service/event/schemas/spike.z.js +3 -1
- package/dist/cjs/src/service/event/spike.d.ts +2 -4
- package/dist/cjs/src/service/event/spike.js +5 -3
- package/dist/cjs/src/service/team/base-config.d.ts +10 -0
- package/dist/cjs/src/service/team/base-config.js +14 -0
- package/dist/cjs/src/service/team/blocking-preference.d.ts +3 -1
- package/dist/cjs/src/service/team/blocking-preference.js +2 -1
- package/dist/cjs/src/service/team/default-base-config.d.ts +4 -0
- package/dist/cjs/src/service/team/default-base-config.js +128 -0
- package/dist/cjs/src/service/team/index.d.ts +2 -0
- package/dist/cjs/src/service/team/index.js +2 -0
- package/dist/cjs/src/service/team/schemas/tactics.z.d.ts +17 -2
- package/dist/cjs/src/service/team/schemas/tactics.z.js +24 -4
- package/dist/cjs/src/service/team/schemas/tactics.z.test.js +29 -16
- package/dist/cjs/src/service/team/schemas/team.z.d.ts +17 -2
- package/dist/cjs/src/service/team/tactics.d.ts +3 -0
- package/dist/cjs/src/service/team/tactics.js +2 -1
- package/dist/cjs/src/service/team/team-generator.js +6 -1
- package/dist/esm/src/api/index.d.ts +3 -2
- package/dist/esm/src/api/tactics-player-refs.js +2 -2
- package/dist/esm/src/data/init-models.js +5 -1
- package/dist/esm/src/data/models/base-position-preset.d.ts +22 -0
- package/dist/esm/src/data/models/base-position-preset.js +50 -0
- package/dist/esm/src/data/models/index.d.ts +1 -0
- package/dist/esm/src/data/models/index.js +1 -0
- package/dist/esm/src/data/models/tactics.d.ts +5 -3
- package/dist/esm/src/data/models/tactics.js +4 -0
- package/dist/esm/src/data/transformers/rally-event-injury.test.js +1 -1
- package/dist/esm/src/data/transformers/rally-event-positional.test.js +10 -2
- package/dist/esm/src/data/transformers/rally-event.js +3 -1
- package/dist/esm/src/data/transformers/rally.test.js +2 -2
- package/dist/esm/src/data/transformers/tactics.js +4 -0
- package/dist/esm/src/data/transformers/tactics.test.js +34 -10
- package/dist/esm/src/service/competition/competition-rewards.d.ts +20 -0
- package/dist/esm/src/service/competition/competition-rewards.js +43 -0
- package/dist/esm/src/service/competition/competition-rewards.test.d.ts +1 -0
- package/dist/esm/src/service/competition/competition-rewards.test.js +30 -0
- package/dist/esm/src/service/competition/index.d.ts +2 -0
- package/dist/esm/src/service/competition/index.js +2 -0
- package/dist/esm/src/service/competition/league-rewards.d.ts +21 -0
- package/dist/esm/src/service/competition/league-rewards.js +53 -0
- package/dist/esm/src/service/competition/league-rewards.test.d.ts +1 -0
- package/dist/esm/src/service/competition/league-rewards.test.js +48 -0
- package/dist/esm/src/service/event/schemas/spike.z.js +3 -1
- package/dist/esm/src/service/event/spike.d.ts +2 -4
- package/dist/esm/src/service/event/spike.js +5 -3
- package/dist/esm/src/service/team/base-config.d.ts +10 -0
- package/dist/esm/src/service/team/base-config.js +11 -0
- package/dist/esm/src/service/team/blocking-preference.d.ts +3 -1
- package/dist/esm/src/service/team/blocking-preference.js +1 -0
- package/dist/esm/src/service/team/default-base-config.d.ts +4 -0
- package/dist/esm/src/service/team/default-base-config.js +124 -0
- package/dist/esm/src/service/team/index.d.ts +2 -0
- package/dist/esm/src/service/team/index.js +2 -0
- package/dist/esm/src/service/team/schemas/tactics.z.d.ts +17 -2
- package/dist/esm/src/service/team/schemas/tactics.z.js +24 -4
- package/dist/esm/src/service/team/schemas/tactics.z.test.js +29 -16
- package/dist/esm/src/service/team/schemas/team.z.d.ts +17 -2
- package/dist/esm/src/service/team/tactics.d.ts +3 -0
- package/dist/esm/src/service/team/tactics.js +2 -1
- package/dist/esm/src/service/team/team-generator.js +6 -1
- package/package.json +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const globals_1 = require("@jest/globals");
|
|
4
|
+
const league_rewards_1 = require("./league-rewards");
|
|
5
|
+
// The cumulative per-tier totals the owner specified (2026-08-07). Every entry is the coins a team finishing at
|
|
6
|
+
// that position earns, summing its band and every band below it. Positions past the lowest band earn 0.
|
|
7
|
+
(0, globals_1.describe)('leaguePayoutFor', () => {
|
|
8
|
+
const TIER1 = {
|
|
9
|
+
1: 3000, 2: 2500, 3: 2250, 4: 2000, 5: 1500, 6: 1500, 7: 1500, 8: 1500, 9: 1000, 10: 1000, 11: 1000, 12: 1000, 13: 0, 14: 0, 15: 0, 16: 0
|
|
10
|
+
};
|
|
11
|
+
const TIER2 = {
|
|
12
|
+
1: 1500, 2: 1250, 3: 1000, 4: 1000, 5: 500, 6: 500, 7: 500, 8: 500, 9: 0, 12: 0, 16: 0
|
|
13
|
+
};
|
|
14
|
+
const TIER3 = {
|
|
15
|
+
1: 1000, 2: 750, 3: 500, 4: 500, 5: 0, 8: 0, 16: 0
|
|
16
|
+
};
|
|
17
|
+
(0, globals_1.it)('matches the owner cumulative totals for tier 1', () => {
|
|
18
|
+
for (const [pos, total] of Object.entries(TIER1)) {
|
|
19
|
+
(0, globals_1.expect)((0, league_rewards_1.leaguePayoutFor)(1, Number(pos))).toBe(total);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
(0, globals_1.it)('matches the owner cumulative totals for tier 2', () => {
|
|
23
|
+
for (const [pos, total] of Object.entries(TIER2)) {
|
|
24
|
+
(0, globals_1.expect)((0, league_rewards_1.leaguePayoutFor)(2, Number(pos))).toBe(total);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
(0, globals_1.it)('matches the owner cumulative totals for tier 3', () => {
|
|
28
|
+
for (const [pos, total] of Object.entries(TIER3)) {
|
|
29
|
+
(0, globals_1.expect)((0, league_rewards_1.leaguePayoutFor)(3, Number(pos))).toBe(total);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
(0, globals_1.it)('treats division 3 and lower with the tier-3 table', () => {
|
|
33
|
+
for (const tier of [3, 4, 5, 10]) {
|
|
34
|
+
(0, globals_1.expect)((0, league_rewards_1.leagueRewardTier)(tier)).toBe(3);
|
|
35
|
+
(0, globals_1.expect)((0, league_rewards_1.leaguePayoutFor)(tier, 1)).toBe(1000);
|
|
36
|
+
(0, globals_1.expect)((0, league_rewards_1.leaguePayoutFor)(tier, 4)).toBe(500);
|
|
37
|
+
(0, globals_1.expect)((0, league_rewards_1.leaguePayoutFor)(tier, 5)).toBe(0);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
(0, globals_1.it)('clamps tier 0 or negative to tier 1', () => {
|
|
41
|
+
(0, globals_1.expect)((0, league_rewards_1.leagueRewardTier)(0)).toBe(1);
|
|
42
|
+
(0, globals_1.expect)((0, league_rewards_1.leaguePayoutFor)(0, 1)).toBe(3000);
|
|
43
|
+
});
|
|
44
|
+
(0, globals_1.it)('each tier band table sums to the champion total', () => {
|
|
45
|
+
const sum = (t) => league_rewards_1.LEAGUE_REWARDS[t].reduce((s, r) => s + r.coins, 0);
|
|
46
|
+
(0, globals_1.expect)(sum(1)).toBe(3000);
|
|
47
|
+
(0, globals_1.expect)(sum(2)).toBe(1500);
|
|
48
|
+
(0, globals_1.expect)(sum(3)).toBe(1000);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -5,7 +5,9 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const player_1 = require("../../player");
|
|
6
6
|
const incident_z_1 = require("./incident.z");
|
|
7
7
|
const positional_z_1 = require("./positional.z");
|
|
8
|
-
|
|
8
|
+
// SPIKE(0), TIP(3), DOWN_BALL(4), OVERHAND(5), TOOL(6). 1/2 (legacy LINE_SHOT/REVERSE_CROSS) are retired; the
|
|
9
|
+
// codec (transformToSpike) maps them to 0 before this validates, so they never reach here.
|
|
10
|
+
const spikeTypeValues = [0, 3, 4, 5, 6];
|
|
9
11
|
const spikeFailureValues = [0, 1, 2, 3, 4];
|
|
10
12
|
const courtTargetValues = Array.from({ length: 13 }, (_, i) => i);
|
|
11
13
|
exports.SpikeInputSchema = zod_1.z.object({
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { InPlayEvent } from './in-play-event';
|
|
2
2
|
export declare enum SpikeTypeEnum {
|
|
3
|
-
|
|
4
|
-
LINE_SHOT = 1,
|
|
5
|
-
REVERSE_CROSS = 2,
|
|
3
|
+
SPIKE = 0,
|
|
6
4
|
TIP = 3,
|
|
7
5
|
DOWN_BALL = 4,
|
|
8
6
|
OVERHAND = 5,
|
|
9
7
|
TOOL = 6
|
|
10
8
|
}
|
|
11
|
-
export type SpikeType = SpikeTypeEnum.
|
|
9
|
+
export type SpikeType = SpikeTypeEnum.SPIKE | SpikeTypeEnum.TIP | SpikeTypeEnum.DOWN_BALL | SpikeTypeEnum.OVERHAND | SpikeTypeEnum.TOOL;
|
|
12
10
|
export declare enum SpikeFailureEnum {
|
|
13
11
|
NO_FAILURE = 0,
|
|
14
12
|
FAULT = 1,
|
|
@@ -6,9 +6,11 @@ const in_play_event_1 = require("./in-play-event");
|
|
|
6
6
|
const spike_z_1 = require("./schemas/spike.z");
|
|
7
7
|
var SpikeTypeEnum;
|
|
8
8
|
(function (SpikeTypeEnum) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
// A hard swing (owner 2026-08-03). The cross / line / reverse DIRECTION is not stored: it is fully derivable
|
|
10
|
+
// from the persisted contact + landing coordinates, so a single SPIKE value replaces the old CROSS_SHOT(0) /
|
|
11
|
+
// LINE_SHOT(1) / REVERSE_CROSS(2). 1 and 2 are retired (left as gaps); the codec maps any legacy 1/2 back to
|
|
12
|
+
// SPIKE(0), so existing (zone-engine) matches keep decoding.
|
|
13
|
+
SpikeTypeEnum[SpikeTypeEnum["SPIKE"] = 0] = "SPIKE";
|
|
12
14
|
SpikeTypeEnum[SpikeTypeEnum["TIP"] = 3] = "TIP";
|
|
13
15
|
SpikeTypeEnum[SpikeTypeEnum["DOWN_BALL"] = 4] = "DOWN_BALL";
|
|
14
16
|
SpikeTypeEnum[SpikeTypeEnum["OVERHAND"] = 5] = "OVERHAND";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type BaseFormation = 'SERVE' | 'RECEIVE' | 'DEFENCE' | 'DEF_L' | 'DEF_M' | 'DEF_R' | 'ATTACK';
|
|
2
|
+
export declare const BASE_FORMATIONS: readonly BaseFormation[];
|
|
3
|
+
export interface BaseCoord {
|
|
4
|
+
readonly d: number;
|
|
5
|
+
readonly r: number;
|
|
6
|
+
}
|
|
7
|
+
export interface BaseConfig {
|
|
8
|
+
readonly coords: Record<string, Record<string, Record<string, BaseCoord>>>;
|
|
9
|
+
readonly receive: Record<string, Record<string, boolean>>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Per-team base-position configuration (owner 2026-08-03). Generalises the sim's hardcoded 5-1 preset into a
|
|
3
|
+
// system-agnostic, per-team shape: for each formation, rotation and rotational ZONE, where that zone's player
|
|
4
|
+
// stands, plus (serve-receive only) whether that zone's player passes the serve. Authored in the UI base editor
|
|
5
|
+
// (and populated from a picked default preset); consumed by the positional engine to place players. A team with no
|
|
6
|
+
// `basePositions` falls back to the default preset for its `rotationSystem`.
|
|
7
|
+
//
|
|
8
|
+
// KEYING: rotation 1..6 and zone 1..6 are the ROTATIONAL (at-the-whistle) slots. The stored rotation convention is
|
|
9
|
+
// the ENGINE's (SETTER_ZONE_TO_ROTATION); the UI editor re-keys the mapper's setter-zone rotation to it on save.
|
|
10
|
+
// `coords[formation][rotation][zone]` is the standing coordinate for that formation; `receive[rotation][zone]` is
|
|
11
|
+
// the reception-participation flag (absent zone => default to participating).
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.BASE_FORMATIONS = void 0;
|
|
14
|
+
exports.BASE_FORMATIONS = ['SERVE', 'RECEIVE', 'DEFENCE', 'DEF_L', 'DEF_M', 'DEF_R', 'ATTACK'];
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { LineupFunction } from './lineup-function';
|
|
2
2
|
export declare const NO_BLOCK: "NO_BLOCK";
|
|
3
3
|
export type BlockingAssignment = LineupFunction | typeof NO_BLOCK;
|
|
4
|
+
export type DefenceFormation = 'DEF_L' | 'DEF_M' | 'DEF_R';
|
|
5
|
+
export declare const DEFENCE_FORMATIONS: readonly DefenceFormation[];
|
|
4
6
|
export interface BlockingPreference {
|
|
5
7
|
readonly rotation: number;
|
|
6
|
-
readonly targets: Record<string, BlockingAssignment
|
|
8
|
+
readonly targets: Record<DefenceFormation, Record<string, BlockingAssignment>>;
|
|
7
9
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NO_BLOCK = void 0;
|
|
3
|
+
exports.DEFENCE_FORMATIONS = exports.NO_BLOCK = void 0;
|
|
4
4
|
// A front-row player opted OUT of blocking for this rotation. They never join the wall under any circumstance:
|
|
5
5
|
// not as the lead blocker (the lane's next-nearest front-row player leads instead), not as a side blocker, and
|
|
6
6
|
// no trait can coerce them in -- MOVING_WALL's guaranteed lead hand, its beaten-read hand and its side-joiner
|
|
7
7
|
// roll are all suppressed, as is a dedicated-blocking commit. Sits in the same `targets` map as a commit
|
|
8
8
|
// assignment, so the two are mutually exclusive by construction: a player is reading, committed, or out.
|
|
9
9
|
exports.NO_BLOCK = 'NO_BLOCK';
|
|
10
|
+
exports.DEFENCE_FORMATIONS = ['DEF_L', 'DEF_M', 'DEF_R'];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BaseConfig } from './base-config';
|
|
2
|
+
import { RotationSystemEnum } from './rotation-system';
|
|
3
|
+
export declare function defaultReceiveMap(system: RotationSystemEnum): BaseConfig['receive'];
|
|
4
|
+
export declare function defaultBaseConfig(system: RotationSystemEnum): BaseConfig;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultReceiveMap = defaultReceiveMap;
|
|
4
|
+
exports.defaultBaseConfig = defaultBaseConfig;
|
|
5
|
+
const lineup_function_1 = require("./lineup-function");
|
|
6
|
+
const player_1 = require("../player");
|
|
7
|
+
const match_1 = require("../match");
|
|
8
|
+
const COORDS = {
|
|
9
|
+
SERVE: {
|
|
10
|
+
1: { 1: { d: 9.90, r: 3.15 }, 2: { d: 0.30, r: -2.55 }, 3: { d: 0.40, r: 0.00 }, 4: { d: 0.30, r: 2.55 }, 5: { d: 6.90, r: -0.15 }, 6: { d: 5.20, r: -2.35 } },
|
|
11
|
+
2: { 1: { d: 10.10, r: 3.00 }, 2: { d: 0.45, r: 0.00 }, 3: { d: 0.55, r: 2.95 }, 4: { d: 0.45, r: -2.95 }, 5: { d: 5.20, r: -2.95 }, 6: { d: 5.25, r: 3.35 } },
|
|
12
|
+
3: { 1: { d: 10.45, r: -3.40 }, 2: { d: 0.35, r: 2.70 }, 3: { d: 0.25, r: -3.00 }, 4: { d: 0.30, r: 0.00 }, 5: { d: 5.35, r: 2.55 }, 6: { d: 6.90, r: -0.05 } },
|
|
13
|
+
4: { 1: { d: 10.50, r: 3.40 }, 2: { d: 0.35, r: -3.05 }, 3: { d: 0.45, r: 0.00 }, 4: { d: 0.45, r: 2.55 }, 5: { d: 7.25, r: 0.15 }, 6: { d: 6.25, r: -2.55 } },
|
|
14
|
+
5: { 1: { d: 10.05, r: 3.50 }, 2: { d: 0.30, r: 0.10 }, 3: { d: 0.25, r: 2.85 }, 4: { d: 0.25, r: -2.80 }, 5: { d: 5.10, r: -2.65 }, 6: { d: 5.15, r: 2.70 } },
|
|
15
|
+
6: { 1: { d: 10.30, r: -3.50 }, 2: { d: 0.65, r: 2.60 }, 3: { d: 0.50, r: -2.55 }, 4: { d: 0.55, r: 0.05 }, 5: { d: 6.45, r: 2.65 }, 6: { d: 6.90, r: 0.10 } }
|
|
16
|
+
},
|
|
17
|
+
RECEIVE: {
|
|
18
|
+
1: { 1: { d: 6.75, r: 2.85 }, 2: { d: 6.25, r: 2.05 }, 3: { d: 3.10, r: -3.65 }, 4: { d: 3.80, r: -4.10 }, 5: { d: 6.40, r: -2.80 }, 6: { d: 6.50, r: 0.00 } },
|
|
19
|
+
2: { 1: { d: 6.00, r: 2.50 }, 2: { d: 3.15, r: 4.00 }, 3: { d: 0.50, r: 0.40 }, 4: { d: 5.85, r: -2.85 }, 5: { d: 6.20, r: -0.05 }, 6: { d: 1.50, r: 0.65 } },
|
|
20
|
+
3: { 1: { d: 6.10, r: 2.55 }, 2: { d: 3.15, r: 4.10 }, 3: { d: 6.50, r: -2.80 }, 4: { d: 0.80, r: -3.70 }, 5: { d: 1.10, r: -1.00 }, 6: { d: 6.65, r: -0.10 } },
|
|
21
|
+
4: { 1: { d: 8.45, r: 3.20 }, 2: { d: 6.25, r: -2.85 }, 3: { d: 1.35, r: -3.70 }, 4: { d: 0.50, r: -4.05 }, 5: { d: 6.75, r: -0.35 }, 6: { d: 6.55, r: 2.40 } },
|
|
22
|
+
5: { 1: { d: 5.90, r: 2.65 }, 2: { d: 2.60, r: 3.90 }, 3: { d: 0.65, r: 1.50 }, 4: { d: 6.05, r: -3.05 }, 5: { d: 6.10, r: 0.10 }, 6: { d: 8.45, r: 0.65 } },
|
|
23
|
+
6: { 1: { d: 6.25, r: 2.60 }, 2: { d: 0.80, r: 1.50 }, 3: { d: 6.40, r: -2.60 }, 4: { d: 3.30, r: -4.30 }, 5: { d: 8.65, r: -2.15 }, 6: { d: 6.70, r: 0.00 } }
|
|
24
|
+
},
|
|
25
|
+
DEFENCE: {
|
|
26
|
+
1: { 1: { d: 5.95, r: 2.65 }, 2: { d: 0.55, r: -2.95 }, 3: { d: 0.50, r: -0.20 }, 4: { d: 0.45, r: 2.70 }, 5: { d: 6.30, r: -0.30 }, 6: { d: 5.90, r: -3.15 } },
|
|
27
|
+
2: { 1: { d: 6.30, r: -0.40 }, 2: { d: 0.05, r: -0.10 }, 3: { d: 0.05, r: 2.70 }, 4: { d: 0.05, r: -2.85 }, 5: { d: 5.50, r: -3.00 }, 6: { d: 5.55, r: 2.80 } },
|
|
28
|
+
3: { 1: { d: 5.25, r: -2.65 }, 2: { d: 0.05, r: 3.05 }, 3: { d: 0.05, r: -2.80 }, 4: { d: 0.05, r: 0.30 }, 5: { d: 5.35, r: 2.95 }, 6: { d: 6.45, r: 0.20 } },
|
|
29
|
+
4: { 1: { d: 6.00, r: 2.90 }, 2: { d: 0.35, r: -3.10 }, 3: { d: 0.25, r: -0.05 }, 4: { d: 0.35, r: 3.10 }, 5: { d: 6.35, r: -0.10 }, 6: { d: 6.00, r: -2.60 } },
|
|
30
|
+
5: { 1: { d: 6.30, r: 0.00 }, 2: { d: 0.10, r: -0.05 }, 3: { d: 0.05, r: 3.00 }, 4: { d: 0.05, r: -3.05 }, 5: { d: 5.90, r: -2.90 }, 6: { d: 6.15, r: 3.25 } },
|
|
31
|
+
6: { 1: { d: 5.70, r: -2.85 }, 2: { d: 0.55, r: 2.50 }, 3: { d: 0.50, r: -2.95 }, 4: { d: 0.50, r: -0.25 }, 5: { d: 5.80, r: 2.90 }, 6: { d: 6.95, r: 0.00 } }
|
|
32
|
+
},
|
|
33
|
+
DEF_L: {
|
|
34
|
+
1: { 1: { d: 5.80, r: 1.50 }, 2: { d: 0.05, r: -3.40 }, 3: { d: 0.05, r: -2.85 }, 4: { d: 1.80, r: 1.30 }, 5: { d: 8.00, r: 0.65 }, 6: { d: 4.50, r: -4.20 } },
|
|
35
|
+
2: { 1: { d: 7.95, r: 0.70 }, 2: { d: 0.05, r: -2.85 }, 3: { d: 1.80, r: 1.30 }, 4: { d: 0.10, r: -3.40 }, 5: { d: 4.50, r: -4.20 }, 6: { d: 5.80, r: 1.50 } },
|
|
36
|
+
3: { 1: { d: 0.05, r: -2.85 }, 2: { d: 1.80, r: 1.30 }, 3: { d: 0.05, r: -3.45 }, 4: { d: 4.50, r: -4.20 }, 5: { d: 5.80, r: 1.50 }, 6: { d: 8.05, r: 0.70 } },
|
|
37
|
+
4: { 1: { d: 5.85, r: 1.50 }, 2: { d: 0.05, r: -3.45 }, 3: { d: 4.50, r: -4.20 }, 4: { d: 1.80, r: 1.30 }, 5: { d: 8.00, r: 0.95 }, 6: { d: 0.05, r: -2.85 } },
|
|
38
|
+
5: { 1: { d: 8.10, r: 0.80 }, 2: { d: 4.50, r: -4.20 }, 3: { d: 1.80, r: 1.30 }, 4: { d: 0.05, r: -3.45 }, 5: { d: 0.05, r: -2.85 }, 6: { d: 5.85, r: 1.50 } },
|
|
39
|
+
6: { 1: { d: 4.50, r: -4.20 }, 2: { d: 1.80, r: 1.30 }, 3: { d: 0.05, r: -3.45 }, 4: { d: 0.05, r: -2.85 }, 5: { d: 5.85, r: 1.50 }, 6: { d: 8.10, r: 0.80 } }
|
|
40
|
+
},
|
|
41
|
+
DEF_M: {
|
|
42
|
+
1: { 1: { d: 4.95, r: 2.35 }, 2: { d: 1.70, r: -2.60 }, 3: { d: 0.05, r: -0.15 }, 4: { d: 2.00, r: 2.80 }, 5: { d: 7.20, r: 1.00 }, 6: { d: 4.70, r: -2.35 } },
|
|
43
|
+
2: { 1: { d: 7.15, r: 1.00 }, 2: { d: 0.05, r: -0.15 }, 3: { d: 2.00, r: 2.80 }, 4: { d: 1.70, r: -2.60 }, 5: { d: 4.70, r: -2.35 }, 6: { d: 4.95, r: 2.35 } },
|
|
44
|
+
3: { 1: { d: 4.95, r: -2.35 }, 2: { d: 2.00, r: 2.80 }, 3: { d: 2.35, r: -2.65 }, 4: { d: 0.05, r: 0.00 }, 5: { d: 4.95, r: 2.35 }, 6: { d: 7.00, r: 1.20 } },
|
|
45
|
+
4: { 1: { d: 4.95, r: 2.15 }, 2: { d: 1.70, r: -2.60 }, 3: { d: 0.15, r: -0.10 }, 4: { d: 2.00, r: 2.85 }, 5: { d: 7.15, r: 1.00 }, 6: { d: 4.95, r: -2.25 } },
|
|
46
|
+
5: { 1: { d: 7.25, r: 1.10 }, 2: { d: 0.05, r: 0.00 }, 3: { d: 1.95, r: 2.60 }, 4: { d: 1.70, r: -2.50 }, 5: { d: 4.85, r: -2.05 }, 6: { d: 5.00, r: 2.15 } },
|
|
47
|
+
6: { 1: { d: 4.70, r: -2.35 }, 2: { d: 2.00, r: 2.75 }, 3: { d: 1.80, r: -2.65 }, 4: { d: 0.05, r: -0.15 }, 5: { d: 4.80, r: 2.40 }, 6: { d: 7.40, r: 1.00 } }
|
|
48
|
+
},
|
|
49
|
+
DEF_R: {
|
|
50
|
+
1: { 1: { d: 4.45, r: 4.20 }, 2: { d: 1.90, r: -1.50 }, 3: { d: 0.10, r: 2.90 }, 4: { d: 0.10, r: 3.45 }, 5: { d: 8.80, r: 0.45 }, 6: { d: 5.25, r: -1.45 } },
|
|
51
|
+
2: { 1: { d: 8.55, r: -0.65 }, 2: { d: 0.05, r: 2.90 }, 3: { d: 0.05, r: 3.50 }, 4: { d: 2.00, r: -2.20 }, 5: { d: 4.80, r: -1.60 }, 6: { d: 4.50, r: 4.15 } },
|
|
52
|
+
3: { 1: { d: 4.75, r: -1.70 }, 2: { d: 0.05, r: 3.45 }, 3: { d: 1.60, r: -1.75 }, 4: { d: 0.05, r: 2.85 }, 5: { d: 4.55, r: 4.15 }, 6: { d: 8.40, r: -0.35 } },
|
|
53
|
+
4: { 1: { d: 5.20, r: 4.15 }, 2: { d: 1.75, r: -1.85 }, 3: { d: 0.05, r: 3.20 }, 4: { d: 0.05, r: 3.75 }, 5: { d: 8.45, r: -0.65 }, 6: { d: 5.15, r: -1.85 } },
|
|
54
|
+
5: { 1: { d: 8.35, r: -0.75 }, 2: { d: 0.05, r: 2.90 }, 3: { d: 0.05, r: 3.50 }, 4: { d: 1.80, r: -1.25 }, 5: { d: 5.25, r: -1.70 }, 6: { d: 5.00, r: 4.15 } },
|
|
55
|
+
6: { 1: { d: 5.15, r: -1.50 }, 2: { d: 0.05, r: 3.45 }, 3: { d: 2.55, r: -2.40 }, 4: { d: 0.05, r: 2.90 }, 5: { d: 4.60, r: 4.10 }, 6: { d: 8.75, r: 0.25 } }
|
|
56
|
+
},
|
|
57
|
+
ATTACK: {
|
|
58
|
+
1: { 1: { d: 0.50, r: 1.55 }, 2: { d: 3.40, r: -5.15 }, 3: { d: 1.15, r: 0.40 }, 4: { d: 4.80, r: 5.20 }, 5: { d: 6.50, r: 0.20 }, 6: { d: 4.85, r: -2.90 } },
|
|
59
|
+
2: { 1: { d: 6.50, r: -0.40 }, 2: { d: 1.60, r: 0.75 }, 3: { d: 3.65, r: 5.05 }, 4: { d: 3.50, r: -5.05 }, 5: { d: 4.45, r: -2.60 }, 6: { d: 0.50, r: 1.60 } },
|
|
60
|
+
3: { 1: { d: 5.05, r: -1.90 }, 2: { d: 3.95, r: 5.00 }, 3: { d: 3.95, r: -4.90 }, 4: { d: 1.80, r: 1.10 }, 5: { d: 0.35, r: 1.55 }, 6: { d: 6.45, r: 0.15 } },
|
|
61
|
+
4: { 1: { d: 6.15, r: 4.95 }, 2: { d: 3.95, r: -5.05 }, 3: { d: 1.45, r: 1.05 }, 4: { d: 0.45, r: 1.80 }, 5: { d: 6.45, r: -0.50 }, 6: { d: 4.95, r: -2.00 } },
|
|
62
|
+
5: { 1: { d: 6.50, r: -0.40 }, 2: { d: 1.80, r: 1.10 }, 3: { d: 0.25, r: 1.85 }, 4: { d: 3.45, r: -4.95 }, 5: { d: 5.35, r: -2.55 }, 6: { d: 6.50, r: 4.90 } },
|
|
63
|
+
6: { 1: { d: 5.85, r: -2.20 }, 2: { d: 0.55, r: 2.00 }, 3: { d: 4.00, r: -4.85 }, 4: { d: 1.35, r: 1.40 }, 5: { d: 6.85, r: 4.90 }, 6: { d: 6.60, r: 0.35 } }
|
|
64
|
+
},
|
|
65
|
+
ATK_L: {
|
|
66
|
+
1: { 1: { d: 0.75, r: 0.10 }, 2: { d: 0.50, r: -4.05 }, 3: { d: 0.95, r: -2.55 }, 4: { d: 3.45, r: 0.80 }, 5: { d: 6.25, r: -0.75 }, 6: { d: 3.60, r: -3.95 } },
|
|
67
|
+
2: { 1: { d: 0.50, r: -4.05 }, 2: { d: 0.95, r: -2.55 }, 3: { d: 3.75, r: 1.05 }, 4: { d: 6.25, r: -0.75 }, 5: { d: 3.60, r: -3.95 }, 6: { d: 0.75, r: 0.10 } },
|
|
68
|
+
3: { 1: { d: 0.95, r: -2.55 }, 2: { d: 3.45, r: 0.80 }, 3: { d: 6.25, r: -0.75 }, 4: { d: 3.60, r: -3.95 }, 5: { d: 0.75, r: 0.10 }, 6: { d: 0.50, r: -4.05 } },
|
|
69
|
+
4: { 1: { d: 3.60, r: 0.90 }, 2: { d: 0.55, r: -4.05 }, 3: { d: 1.15, r: -2.60 }, 4: { d: 0.85, r: 0.25 }, 5: { d: 6.25, r: -0.80 }, 6: { d: 3.45, r: -4.10 } },
|
|
70
|
+
5: { 1: { d: 6.25, r: -0.65 }, 2: { d: 1.20, r: -2.55 }, 3: { d: 0.80, r: 0.10 }, 4: { d: 0.50, r: -4.10 }, 5: { d: 3.90, r: -4.00 }, 6: { d: 3.75, r: 0.80 } },
|
|
71
|
+
6: { 1: { d: 3.60, r: -3.95 }, 2: { d: 0.75, r: 0.10 }, 3: { d: 0.50, r: -4.05 }, 4: { d: 0.95, r: -2.55 }, 5: { d: 3.45, r: 0.80 }, 6: { d: 6.25, r: -0.75 } }
|
|
72
|
+
},
|
|
73
|
+
ATK_M: {
|
|
74
|
+
1: { 1: { d: 0.60, r: 1.25 }, 2: { d: 1.20, r: -2.00 }, 3: { d: 0.70, r: 0.50 }, 4: { d: 2.25, r: 2.60 }, 5: { d: 6.40, r: 1.40 }, 6: { d: 4.05, r: -1.55 } },
|
|
75
|
+
2: { 1: { d: 6.65, r: 1.55 }, 2: { d: 0.70, r: 0.50 }, 3: { d: 2.25, r: 2.60 }, 4: { d: 1.40, r: -1.90 }, 5: { d: 4.05, r: -1.55 }, 6: { d: 0.60, r: 1.25 } },
|
|
76
|
+
3: { 1: { d: 4.05, r: -1.55 }, 2: { d: 2.25, r: 2.60 }, 3: { d: 1.20, r: -2.00 }, 4: { d: 0.70, r: 0.45 }, 5: { d: 0.65, r: 1.15 }, 6: { d: 6.40, r: 1.40 } },
|
|
77
|
+
4: { 1: { d: 2.25, r: 2.60 }, 2: { d: 1.35, r: -1.90 }, 3: { d: 0.65, r: 0.50 }, 4: { d: 0.60, r: 1.25 }, 5: { d: 6.40, r: 1.45 }, 6: { d: 4.15, r: -1.45 } },
|
|
78
|
+
5: { 1: { d: 6.40, r: 1.40 }, 2: { d: 0.65, r: 0.50 }, 3: { d: 0.60, r: 1.25 }, 4: { d: 1.20, r: -2.00 }, 5: { d: 4.15, r: -1.40 }, 6: { d: 2.25, r: 2.60 } },
|
|
79
|
+
6: { 1: { d: 4.05, r: -1.55 }, 2: { d: 0.60, r: 1.25 }, 3: { d: 1.20, r: -2.00 }, 4: { d: 0.70, r: 0.50 }, 5: { d: 2.25, r: 2.60 }, 6: { d: 6.40, r: 1.40 } }
|
|
80
|
+
},
|
|
81
|
+
ATK_R: {
|
|
82
|
+
1: { 1: { d: 1.75, r: 2.60 }, 2: { d: 1.60, r: -1.75 }, 3: { d: 0.75, r: 1.80 }, 4: { d: 0.60, r: 3.90 }, 5: { d: 4.90, r: 3.25 }, 6: { d: 5.85, r: -1.90 } },
|
|
83
|
+
2: { 1: { d: 5.15, r: 3.20 }, 2: { d: 0.75, r: 1.80 }, 3: { d: 0.60, r: 3.90 }, 4: { d: 1.60, r: -1.40 }, 5: { d: 5.85, r: -1.90 }, 6: { d: 1.75, r: 2.60 } },
|
|
84
|
+
3: { 1: { d: 6.05, r: -2.00 }, 2: { d: 0.60, r: 3.90 }, 3: { d: 1.55, r: -1.55 }, 4: { d: 0.75, r: 1.70 }, 5: { d: 1.75, r: 2.60 }, 6: { d: 5.05, r: 3.15 } },
|
|
85
|
+
4: { 1: { d: 2.25, r: 4.20 }, 2: { d: 2.40, r: -1.65 }, 3: { d: 0.85, r: 1.40 }, 4: { d: 1.40, r: 2.30 }, 5: { d: 6.00, r: 1.85 }, 6: { d: 5.25, r: -0.90 } },
|
|
86
|
+
5: { 1: { d: 5.95, r: 2.35 }, 2: { d: 0.85, r: 1.40 }, 3: { d: 1.40, r: 2.30 }, 4: { d: 2.20, r: -1.80 }, 5: { d: 5.25, r: -0.90 }, 6: { d: 2.25, r: 4.20 } },
|
|
87
|
+
6: { 1: { d: 5.30, r: -0.90 }, 2: { d: 1.45, r: 2.30 }, 3: { d: 2.25, r: -1.80 }, 4: { d: 0.75, r: 1.40 }, 5: { d: 2.25, r: 4.05 }, 6: { d: 5.90, r: 2.35 } }
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
// The default coordinate table as a BaseConfig.coords (jsonb string keys). Shared, readonly; materialized (and so
|
|
91
|
+
// serialized) per team on save, so sharing the reference in memory is safe.
|
|
92
|
+
const DEFAULT_COORDS = (() => {
|
|
93
|
+
const out = {};
|
|
94
|
+
for (const [formation, rotations] of Object.entries(COORDS)) {
|
|
95
|
+
out[formation] = {};
|
|
96
|
+
for (const [rotation, zones] of Object.entries(rotations)) {
|
|
97
|
+
out[formation][rotation] = {};
|
|
98
|
+
for (const [zone, coord] of Object.entries(zones))
|
|
99
|
+
out[formation][rotation][zone] = { d: coord.d, r: coord.r };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
})();
|
|
104
|
+
// 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}).
|
|
105
|
+
const ROTATION_TO_SETTER_ZONE = { 1: 1, 2: 6, 3: 5, 4: 4, 5: 3, 6: 2 };
|
|
106
|
+
// The default serve-receive participation map: the standard 3-passer formation. A rotational slot passes iff its
|
|
107
|
+
// slot function is an OUTSIDE_HITTER (either row) or a BACK-ROW MIDDLE_BLOCKER (the libero's slot). The setter, the
|
|
108
|
+
// opposite and the front-row middle hide. slotFunctionAt maps the opposite slot to SETTER in 4-2/6-2, so the
|
|
109
|
+
// second setter is excluded too, giving the same 3-passer map for every system.
|
|
110
|
+
function defaultReceiveMap(system) {
|
|
111
|
+
const receive = {};
|
|
112
|
+
for (let rotation = 1; rotation <= 6; rotation++) {
|
|
113
|
+
const setterZone = ROTATION_TO_SETTER_ZONE[rotation];
|
|
114
|
+
const perZone = {};
|
|
115
|
+
for (let zone = 1; zone <= 6; zone++) {
|
|
116
|
+
const fn = (0, lineup_function_1.slotFunctionAt)(system, setterZone, zone);
|
|
117
|
+
perZone[String(zone)] = fn === player_1.RoleEnum.OUTSIDE_HITTER || (fn === player_1.RoleEnum.MIDDLE_BLOCKER && (0, match_1.isBackRow)(zone));
|
|
118
|
+
}
|
|
119
|
+
receive[String(rotation)] = perZone;
|
|
120
|
+
}
|
|
121
|
+
return receive;
|
|
122
|
+
}
|
|
123
|
+
// The default base config a team of the given system starts with. Every team always has one (materialized on team
|
|
124
|
+
// creation and by the backfill migration); the coordinates are the same 5-1 table for every system, only the
|
|
125
|
+
// receive map is derived per system.
|
|
126
|
+
function defaultBaseConfig(system) {
|
|
127
|
+
return { coords: DEFAULT_COORDS, receive: defaultReceiveMap(system) };
|
|
128
|
+
}
|
|
@@ -2,6 +2,8 @@ export * from './team';
|
|
|
2
2
|
export * from './team-generator';
|
|
3
3
|
export * from './formation';
|
|
4
4
|
export * from './tactics';
|
|
5
|
+
export * from './base-config';
|
|
6
|
+
export * from './default-base-config';
|
|
5
7
|
export * from './team-name';
|
|
6
8
|
export * from './energy-band';
|
|
7
9
|
export * from './pinch-condition';
|
|
@@ -18,6 +18,8 @@ __exportStar(require("./team"), exports);
|
|
|
18
18
|
__exportStar(require("./team-generator"), exports);
|
|
19
19
|
__exportStar(require("./formation"), exports);
|
|
20
20
|
__exportStar(require("./tactics"), exports);
|
|
21
|
+
__exportStar(require("./base-config"), exports);
|
|
22
|
+
__exportStar(require("./default-base-config"), exports);
|
|
21
23
|
__exportStar(require("./team-name"), exports);
|
|
22
24
|
__exportStar(require("./energy-band"), exports);
|
|
23
25
|
__exportStar(require("./pinch-condition"), exports);
|
|
@@ -282,12 +282,27 @@ export declare const TacticsInputSchema: z.ZodObject<{
|
|
|
282
282
|
}, z.core.$strip>>>>;
|
|
283
283
|
blockingPreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
284
284
|
rotation: z.ZodNumber;
|
|
285
|
-
targets: z.
|
|
285
|
+
targets: z.ZodObject<{
|
|
286
|
+
DEF_L: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
287
|
+
DEF_M: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
288
|
+
DEF_R: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
289
|
+
}, z.core.$strip>;
|
|
286
290
|
}, z.core.$strip>>>;
|
|
287
291
|
blockingPreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
288
292
|
rotation: z.ZodNumber;
|
|
289
|
-
targets: z.
|
|
293
|
+
targets: z.ZodObject<{
|
|
294
|
+
DEF_L: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
295
|
+
DEF_M: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
296
|
+
DEF_R: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof RoleEnum> & z.ZodType<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum, z.core.$ZodTypeInternals<RoleEnum.SETTER | RoleEnum.OUTSIDE_HITTER | RoleEnum.OPPOSITE_HITTER | RoleEnum.MIDDLE_BLOCKER, RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
297
|
+
}, z.core.$strip>;
|
|
290
298
|
}, z.core.$strip>>>>;
|
|
299
|
+
basePositions: z.ZodOptional<z.ZodObject<{
|
|
300
|
+
coords: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
301
|
+
d: z.ZodNumber;
|
|
302
|
+
r: z.ZodNumber;
|
|
303
|
+
}, z.core.$strip>>>>;
|
|
304
|
+
receive: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
305
|
+
}, z.core.$strip>>;
|
|
291
306
|
replaceKnockedImmediately: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
292
307
|
injuryReplacements: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
293
308
|
starter: z.ZodCustom<Player, Player>;
|
|
@@ -68,15 +68,31 @@ const blockingFunctionSchema = zod_1.z.union([
|
|
|
68
68
|
]);
|
|
69
69
|
// One rotation's dedicated-blocking assignments: `targets` maps my front-row starter ids to the opposing function
|
|
70
70
|
// each commits to block. Cross-field checks (keys are starters) live in the superRefine below.
|
|
71
|
+
const blockingTargetsSchema = zod_1.z.record(zod_1.z.string(), blockingFunctionSchema);
|
|
72
|
+
// Per point-of-attack defence (owner 2026-08-06): a separate front-row commit map for an attack from my left /
|
|
73
|
+
// middle / right. Each defaults to {} so a partial config stays valid.
|
|
71
74
|
const blockingPreferenceSchema = zod_1.z.object({
|
|
72
75
|
rotation: zod_1.z.number().int().min(1).max(6),
|
|
73
|
-
targets: zod_1.z.
|
|
76
|
+
targets: zod_1.z.object({
|
|
77
|
+
DEF_L: blockingTargetsSchema.default({}),
|
|
78
|
+
DEF_M: blockingTargetsSchema.default({}),
|
|
79
|
+
DEF_R: blockingTargetsSchema.default({})
|
|
80
|
+
})
|
|
74
81
|
});
|
|
75
82
|
// One set's rotation-system override (per-set tactics): system + its designated setters travel together.
|
|
76
83
|
const systemSetSchema = zod_1.z.object({
|
|
77
84
|
rotationSystem: zod_1.z.nativeEnum(rotation_system_1.RotationSystemEnum),
|
|
78
85
|
designatedSetters: zod_1.z.array(playerInstanceSchema)
|
|
79
86
|
});
|
|
87
|
+
// Base positions (owner 2026-08-03): coords[formation][rotation][zone] -> {d,r} + receive[rotation][zone] -> bool.
|
|
88
|
+
// jsonb keys are strings; the coordinate + boolean leaves are validated. Structural key ranges (formation names,
|
|
89
|
+
// rotations 1-6, zones 1-6) are trusted from the UI editor / preset compiler, which write the engine rotation
|
|
90
|
+
// convention. Out-of-court coordinates are allowed, so d/r are not range-clamped here.
|
|
91
|
+
const baseCoordSchema = zod_1.z.object({ d: zod_1.z.number().finite(), r: zod_1.z.number().finite() });
|
|
92
|
+
const baseConfigSchema = zod_1.z.object({
|
|
93
|
+
coords: zod_1.z.record(zod_1.z.string(), zod_1.z.record(zod_1.z.string(), zod_1.z.record(zod_1.z.string(), baseCoordSchema))),
|
|
94
|
+
receive: zod_1.z.record(zod_1.z.string(), zod_1.z.record(zod_1.z.string(), zod_1.z.boolean()))
|
|
95
|
+
});
|
|
80
96
|
exports.TacticsInputSchema = zod_1.z.object({
|
|
81
97
|
lineup: lineupSchema,
|
|
82
98
|
liberoReplacements: zod_1.z.array(playerInstanceSchema),
|
|
@@ -107,6 +123,8 @@ exports.TacticsInputSchema = zod_1.z.object({
|
|
|
107
123
|
// Blocking preferences (dedicated blocking). Defaults keep every existing Tactics.create({...}) call valid.
|
|
108
124
|
blockingPreferences: zod_1.z.array(blockingPreferenceSchema).default([]),
|
|
109
125
|
blockingPreferenceSets: zod_1.z.array(zod_1.z.array(blockingPreferenceSchema)).max(5).optional(),
|
|
126
|
+
// Base positions (owner 2026-08-03). Optional -> the sim falls back to the default preset for the system.
|
|
127
|
+
basePositions: baseConfigSchema.optional(),
|
|
110
128
|
// Injuries. Defaults keep every existing Tactics.create({...}) call valid. replaceKnockedImmediately is
|
|
111
129
|
// PER STARTER (owner order 2026-07-05): keyed by starter id, missing key = ON; keys validated against the
|
|
112
130
|
// lineup in the superRefine below. injuryReplacements is the per-starter explicit replacement mapping
|
|
@@ -202,9 +220,11 @@ exports.TacticsInputSchema = zod_1.z.object({
|
|
|
202
220
|
ctx.addIssue({ code: 'custom', message: 'BLOCKING_PREFERENCE_DUPLICATE_ROTATION', path });
|
|
203
221
|
}
|
|
204
222
|
seenRotations.add(pref.rotation);
|
|
205
|
-
for (const
|
|
206
|
-
|
|
207
|
-
|
|
223
|
+
for (const form of ['DEF_L', 'DEF_M', 'DEF_R']) {
|
|
224
|
+
for (const id of Object.keys(pref.targets[form] ?? {})) {
|
|
225
|
+
if (!starterIds.has(id)) {
|
|
226
|
+
ctx.addIssue({ code: 'custom', message: 'BLOCKING_PREFERENCE_BLOCKER_NOT_A_STARTER', path });
|
|
227
|
+
}
|
|
208
228
|
}
|
|
209
229
|
}
|
|
210
230
|
}
|
|
@@ -236,18 +236,31 @@ const test_helpers_1 = require("../../test-helpers");
|
|
|
236
236
|
...overrides
|
|
237
237
|
};
|
|
238
238
|
}
|
|
239
|
-
(0, globals_1.it)('accepts a blocking preference that keys starters to attacking functions', () => {
|
|
239
|
+
(0, globals_1.it)('accepts a blocking preference that keys starters to attacking functions, per defence side', () => {
|
|
240
240
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
241
|
-
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: player_1.RoleEnum.OUTSIDE_HITTER, [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } }]
|
|
241
|
+
blockingPreferences: [{ rotation: 1, targets: { DEF_L: { [p4.id]: player_1.RoleEnum.OUTSIDE_HITTER }, DEF_M: {}, DEF_R: { [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } } }]
|
|
242
242
|
}));
|
|
243
243
|
(0, globals_1.expect)(res.success).toBe(true);
|
|
244
244
|
if (res.success) {
|
|
245
|
-
(0, globals_1.expect)(res.data.blockingPreferences[0].targets[p4.id]).toBe(player_1.RoleEnum.OUTSIDE_HITTER);
|
|
245
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_L[p4.id]).toBe(player_1.RoleEnum.OUTSIDE_HITTER);
|
|
246
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_R[p3.id]).toBe(player_1.RoleEnum.MIDDLE_BLOCKER);
|
|
247
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_M).toEqual({}); // the middle side is independent (empty here)
|
|
246
248
|
}
|
|
247
249
|
});
|
|
248
|
-
(0, globals_1.it)('
|
|
250
|
+
(0, globals_1.it)('defaults the omitted defence sides to empty maps', () => {
|
|
249
251
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
250
|
-
blockingPreferences: [{ rotation: 1, targets: { [
|
|
252
|
+
blockingPreferences: [{ rotation: 1, targets: { DEF_L: { [p4.id]: blocking_preference_1.NO_BLOCK } } }]
|
|
253
|
+
}));
|
|
254
|
+
(0, globals_1.expect)(res.success).toBe(true);
|
|
255
|
+
if (res.success) {
|
|
256
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_L[p4.id]).toBe(blocking_preference_1.NO_BLOCK);
|
|
257
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_M).toEqual({});
|
|
258
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_R).toEqual({});
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
(0, globals_1.it)('rejects a blocking target (on any side) that is not a starter', () => {
|
|
262
|
+
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
263
|
+
blockingPreferences: [{ rotation: 1, targets: { DEF_M: { [reserve.id]: player_1.RoleEnum.OUTSIDE_HITTER } } }]
|
|
251
264
|
}));
|
|
252
265
|
(0, globals_1.expect)(res.success).toBe(false);
|
|
253
266
|
if (!res.success) {
|
|
@@ -256,7 +269,7 @@ const test_helpers_1 = require("../../test-helpers");
|
|
|
256
269
|
});
|
|
257
270
|
(0, globals_1.it)('rejects a blocking target function of libero', () => {
|
|
258
271
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
259
|
-
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: player_1.RoleEnum.LIBERO } }]
|
|
272
|
+
blockingPreferences: [{ rotation: 1, targets: { DEF_L: { [p4.id]: player_1.RoleEnum.LIBERO } } }]
|
|
260
273
|
}));
|
|
261
274
|
(0, globals_1.expect)(res.success).toBe(false);
|
|
262
275
|
if (!res.success) {
|
|
@@ -266,8 +279,8 @@ const test_helpers_1 = require("../../test-helpers");
|
|
|
266
279
|
(0, globals_1.it)('rejects a duplicate rotation in blocking preferences', () => {
|
|
267
280
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
268
281
|
blockingPreferences: [
|
|
269
|
-
{ rotation: 1, targets: { [p4.id]: player_1.RoleEnum.OUTSIDE_HITTER } },
|
|
270
|
-
{ rotation: 1, targets: { [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } }
|
|
282
|
+
{ rotation: 1, targets: { DEF_L: { [p4.id]: player_1.RoleEnum.OUTSIDE_HITTER } } },
|
|
283
|
+
{ rotation: 1, targets: { DEF_M: { [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } } }
|
|
271
284
|
]
|
|
272
285
|
}));
|
|
273
286
|
(0, globals_1.expect)(res.success).toBe(false);
|
|
@@ -277,29 +290,29 @@ const test_helpers_1 = require("../../test-helpers");
|
|
|
277
290
|
});
|
|
278
291
|
(0, globals_1.it)('accepts per-set blocking preference overrides', () => {
|
|
279
292
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
280
|
-
blockingPreferenceSets: [[{ rotation: 1, targets: { [p4.id]: player_1.RoleEnum.OPPOSITE_HITTER } }], []]
|
|
293
|
+
blockingPreferenceSets: [[{ rotation: 1, targets: { DEF_R: { [p4.id]: player_1.RoleEnum.OPPOSITE_HITTER } } }], []]
|
|
281
294
|
}));
|
|
282
295
|
(0, globals_1.expect)(res.success).toBe(true);
|
|
283
296
|
});
|
|
284
|
-
(0, globals_1.it)('accepts NO_BLOCK as an assignment, alongside a commit on another starter', () => {
|
|
297
|
+
(0, globals_1.it)('accepts NO_BLOCK as an assignment, alongside a commit on another starter, on the same side', () => {
|
|
285
298
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
286
|
-
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: blocking_preference_1.NO_BLOCK, [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } }]
|
|
299
|
+
blockingPreferences: [{ rotation: 1, targets: { DEF_L: { [p4.id]: blocking_preference_1.NO_BLOCK, [p3.id]: player_1.RoleEnum.MIDDLE_BLOCKER } } }]
|
|
287
300
|
}));
|
|
288
301
|
(0, globals_1.expect)(res.success).toBe(true);
|
|
289
302
|
if (res.success) {
|
|
290
|
-
(0, globals_1.expect)(res.data.blockingPreferences[0].targets[p4.id]).toBe(blocking_preference_1.NO_BLOCK);
|
|
291
|
-
(0, globals_1.expect)(res.data.blockingPreferences[0].targets[p3.id]).toBe(player_1.RoleEnum.MIDDLE_BLOCKER);
|
|
303
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_L[p4.id]).toBe(blocking_preference_1.NO_BLOCK);
|
|
304
|
+
(0, globals_1.expect)(res.data.blockingPreferences[0].targets.DEF_L[p3.id]).toBe(player_1.RoleEnum.MIDDLE_BLOCKER);
|
|
292
305
|
}
|
|
293
306
|
});
|
|
294
307
|
(0, globals_1.it)('accepts NO_BLOCK in a per-set override', () => {
|
|
295
308
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
296
|
-
blockingPreferenceSets: [[{ rotation: 1, targets: { [p4.id]: blocking_preference_1.NO_BLOCK } }], []]
|
|
309
|
+
blockingPreferenceSets: [[{ rotation: 1, targets: { DEF_M: { [p4.id]: blocking_preference_1.NO_BLOCK } } }], []]
|
|
297
310
|
}));
|
|
298
311
|
(0, globals_1.expect)(res.success).toBe(true);
|
|
299
312
|
});
|
|
300
313
|
(0, globals_1.it)('still rejects a NO_BLOCK assignment on a player who is not a starter', () => {
|
|
301
314
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
302
|
-
blockingPreferences: [{ rotation: 1, targets: { [reserve.id]: blocking_preference_1.NO_BLOCK } }]
|
|
315
|
+
blockingPreferences: [{ rotation: 1, targets: { DEF_R: { [reserve.id]: blocking_preference_1.NO_BLOCK } } }]
|
|
303
316
|
}));
|
|
304
317
|
(0, globals_1.expect)(res.success).toBe(false);
|
|
305
318
|
if (!res.success) {
|
|
@@ -308,7 +321,7 @@ const test_helpers_1 = require("../../test-helpers");
|
|
|
308
321
|
});
|
|
309
322
|
(0, globals_1.it)('rejects an unknown assignment string', () => {
|
|
310
323
|
const res = tactics_z_1.TacticsInputSchema.safeParse(baseInput({
|
|
311
|
-
blockingPreferences: [{ rotation: 1, targets: { [p4.id]: 'NO_BLOCKING' } }]
|
|
324
|
+
blockingPreferences: [{ rotation: 1, targets: { DEF_L: { [p4.id]: 'NO_BLOCKING' } } }]
|
|
312
325
|
}));
|
|
313
326
|
(0, globals_1.expect)(res.success).toBe(false);
|
|
314
327
|
});
|
|
@@ -290,12 +290,27 @@ export declare const TeamInputSchema: z.ZodObject<{
|
|
|
290
290
|
}, z.core.$strip>>>>;
|
|
291
291
|
blockingPreferences: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
292
292
|
rotation: z.ZodNumber;
|
|
293
|
-
targets: z.
|
|
293
|
+
targets: z.ZodObject<{
|
|
294
|
+
DEF_L: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
295
|
+
DEF_M: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
296
|
+
DEF_R: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
297
|
+
}, z.core.$strip>;
|
|
294
298
|
}, z.core.$strip>>>;
|
|
295
299
|
blockingPreferenceSets: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodObject<{
|
|
296
300
|
rotation: z.ZodNumber;
|
|
297
|
-
targets: z.
|
|
301
|
+
targets: z.ZodObject<{
|
|
302
|
+
DEF_L: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
303
|
+
DEF_M: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
304
|
+
DEF_R: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodEnum<typeof import("../../player").RoleEnum> & z.ZodType<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum, z.core.$ZodTypeInternals<import("../../player").RoleEnum.SETTER | import("../../player").RoleEnum.OUTSIDE_HITTER | import("../../player").RoleEnum.OPPOSITE_HITTER | import("../../player").RoleEnum.MIDDLE_BLOCKER, import("../../player").RoleEnum>>, z.ZodLiteral<"NO_BLOCK">]>>>;
|
|
305
|
+
}, z.core.$strip>;
|
|
298
306
|
}, z.core.$strip>>>>;
|
|
307
|
+
basePositions: z.ZodOptional<z.ZodObject<{
|
|
308
|
+
coords: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
309
|
+
d: z.ZodNumber;
|
|
310
|
+
r: z.ZodNumber;
|
|
311
|
+
}, z.core.$strip>>>>;
|
|
312
|
+
receive: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
313
|
+
}, z.core.$strip>>;
|
|
299
314
|
replaceKnockedImmediately: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
300
315
|
injuryReplacements: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
301
316
|
starter: z.ZodCustom<Player, Player>;
|
|
@@ -8,6 +8,7 @@ import { OffensivePreference } from './offensive-preference';
|
|
|
8
8
|
import { BlockingPreference } from './blocking-preference';
|
|
9
9
|
import { InjuryReplacement } from './injury-replacement';
|
|
10
10
|
import { LiberoInjuryConfig } from './libero-injury';
|
|
11
|
+
import { BaseConfig } from './base-config';
|
|
11
12
|
export interface StartingLineup {
|
|
12
13
|
readonly [CourtPosition.LEFT_FRONT]: Player;
|
|
13
14
|
readonly [CourtPosition.MIDDLE_FRONT]: Player;
|
|
@@ -42,6 +43,7 @@ export interface TacticsOpts {
|
|
|
42
43
|
readonly liberoInjury?: LiberoInjuryConfig;
|
|
43
44
|
readonly blockingPreferences: BlockingPreference[];
|
|
44
45
|
readonly blockingPreferenceSets?: BlockingPreference[][];
|
|
46
|
+
readonly basePositions?: BaseConfig;
|
|
45
47
|
}
|
|
46
48
|
export declare class Tactics {
|
|
47
49
|
readonly lineup: StartingLineup;
|
|
@@ -63,6 +65,7 @@ export declare class Tactics {
|
|
|
63
65
|
readonly liberoInjury?: LiberoInjuryConfig;
|
|
64
66
|
readonly blockingPreferences: BlockingPreference[];
|
|
65
67
|
readonly blockingPreferenceSets?: BlockingPreference[][];
|
|
68
|
+
readonly basePositions?: BaseConfig;
|
|
66
69
|
static create(input: unknown): Tactics;
|
|
67
70
|
private constructor();
|
|
68
71
|
findPlayerInLineup(id: string): CourtPosition | undefined;
|
|
@@ -18,7 +18,7 @@ class Tactics {
|
|
|
18
18
|
}
|
|
19
19
|
return new Tactics(result.data);
|
|
20
20
|
}
|
|
21
|
-
constructor({ lineup, liberoReplacements, receiveRotationOffset = false, designatedSubs = [], substitutionBand = energy_band_1.EnergyBand.TIRED, secondLibero, liberoSub, liberoReplacementSets, rotationSystem = rotation_system_1.RotationSystemEnum.SIX_ZERO, designatedSetters = [], offensivePreferences = [], serveAttackShares = {}, systemSets, offensivePreferenceSets, replaceKnockedImmediately = {}, injuryReplacements = [], liberoInjury, blockingPreferences = [], blockingPreferenceSets }) {
|
|
21
|
+
constructor({ lineup, liberoReplacements, receiveRotationOffset = false, designatedSubs = [], substitutionBand = energy_band_1.EnergyBand.TIRED, secondLibero, liberoSub, liberoReplacementSets, rotationSystem = rotation_system_1.RotationSystemEnum.SIX_ZERO, designatedSetters = [], offensivePreferences = [], serveAttackShares = {}, systemSets, offensivePreferenceSets, replaceKnockedImmediately = {}, injuryReplacements = [], liberoInjury, blockingPreferences = [], blockingPreferenceSets, basePositions }) {
|
|
22
22
|
this.lineup = lineup;
|
|
23
23
|
this.liberoReplacements = liberoReplacements;
|
|
24
24
|
this.receiveRotationOffset = receiveRotationOffset;
|
|
@@ -38,6 +38,7 @@ class Tactics {
|
|
|
38
38
|
this.liberoInjury = liberoInjury;
|
|
39
39
|
this.blockingPreferences = blockingPreferences;
|
|
40
40
|
this.blockingPreferenceSets = blockingPreferenceSets;
|
|
41
|
+
this.basePositions = basePositions;
|
|
41
42
|
}
|
|
42
43
|
findPlayerInLineup(id) {
|
|
43
44
|
if (this.lineup.bench.some(p => p.id === id))
|
|
@@ -11,6 +11,8 @@ const team_1 = require("./team");
|
|
|
11
11
|
const tactics_1 = require("./tactics");
|
|
12
12
|
const energy_band_1 = require("./energy-band");
|
|
13
13
|
const formation_1 = require("./formation");
|
|
14
|
+
const rotation_system_1 = require("./rotation-system");
|
|
15
|
+
const default_base_config_1 = require("./default-base-config");
|
|
14
16
|
const match_1 = require("../match");
|
|
15
17
|
const logger_1 = __importDefault(require("../../logger"));
|
|
16
18
|
const buildBlock = (rarity, count) => Array.from({ length: count }, () => rarity);
|
|
@@ -68,7 +70,10 @@ class TeamGenerator {
|
|
|
68
70
|
return tactics_1.Tactics.create({
|
|
69
71
|
lineup,
|
|
70
72
|
liberoReplacements: [lineup[3], lineup[6]],
|
|
71
|
-
substitutionBand: TeamGenerator.BOT_SUB_BANDS[Math.floor(Math.random() * TeamGenerator.BOT_SUB_BANDS.length)]
|
|
73
|
+
substitutionBand: TeamGenerator.BOT_SUB_BANDS[Math.floor(Math.random() * TeamGenerator.BOT_SUB_BANDS.length)],
|
|
74
|
+
// basePositions is never null: a team always carries the default base config for its system. createTactics
|
|
75
|
+
// makes 6-0 teams (Tactics.create default); when a user picks another system the API re-materializes.
|
|
76
|
+
basePositions: (0, default_base_config_1.defaultBaseConfig)(rotation_system_1.RotationSystemEnum.SIX_ZERO)
|
|
72
77
|
});
|
|
73
78
|
}
|
|
74
79
|
static createLineup(players, formation) {
|