volleyballsimtypes 0.0.481 → 0.0.483
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/api/index.d.ts +10 -18
- package/dist/cjs/src/data/models/tactics.d.ts +17 -19
- package/dist/cjs/src/data/models/tactics.js +9 -0
- package/dist/cjs/src/data/transformers/match-preset-override.test.js +10 -1
- package/dist/cjs/src/data/transformers/rally-event.d.ts +2 -1
- package/dist/cjs/src/data/transformers/rally-event.js +12 -0
- package/dist/cjs/src/data/transformers/rally.js +2 -0
- package/dist/cjs/src/data/transformers/rally.test.d.ts +1 -0
- package/dist/cjs/src/data/transformers/rally.test.js +62 -0
- package/dist/cjs/src/data/transformers/tactics.js +38 -58
- package/dist/cjs/src/data/transformers/tactics.test.js +39 -20
- package/dist/cjs/src/service/team/blocking-preference.d.ts +5 -0
- package/dist/cjs/src/service/team/blocking-preference.js +2 -0
- package/dist/cjs/src/service/team/designated-sub.d.ts +2 -4
- 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/libero-sub.d.ts +0 -4
- package/dist/cjs/src/service/team/offensive-preference.d.ts +1 -2
- package/dist/cjs/src/service/team/pinch-condition.d.ts +11 -3
- package/dist/cjs/src/service/team/pinch-condition.js +9 -4
- package/dist/cjs/src/service/team/schemas/designated-sub.z.d.ts +30 -32
- package/dist/cjs/src/service/team/schemas/designated-sub.z.js +27 -23
- package/dist/cjs/src/service/team/schemas/designated-sub.z.test.js +4 -2
- package/dist/cjs/src/service/team/schemas/libero-sub.z.d.ts +15 -34
- package/dist/cjs/src/service/team/schemas/libero-sub.z.js +10 -26
- package/dist/cjs/src/service/team/schemas/libero-sub.z.test.js +74 -35
- package/dist/cjs/src/service/team/schemas/tactics.z.d.ts +39 -39
- package/dist/cjs/src/service/team/schemas/tactics.z.js +47 -13
- package/dist/cjs/src/service/team/schemas/tactics.z.test.js +81 -8
- package/dist/cjs/src/service/team/schemas/team.z.d.ts +38 -38
- package/dist/cjs/src/service/team/sub-config-convert.d.ts +13 -0
- package/dist/cjs/src/service/team/sub-config-convert.js +91 -0
- package/dist/cjs/src/service/team/sub-config-convert.test.d.ts +1 -0
- package/dist/cjs/src/service/team/sub-config-convert.test.js +84 -0
- package/dist/cjs/src/service/team/tactics.d.ts +5 -0
- package/dist/cjs/src/service/team/tactics.js +3 -1
- package/dist/esm/src/api/index.d.ts +10 -18
- package/dist/esm/src/data/models/tactics.d.ts +17 -19
- package/dist/esm/src/data/models/tactics.js +9 -0
- package/dist/esm/src/data/transformers/match-preset-override.test.js +10 -1
- package/dist/esm/src/data/transformers/rally-event.d.ts +2 -1
- package/dist/esm/src/data/transformers/rally-event.js +12 -1
- package/dist/esm/src/data/transformers/rally.js +4 -2
- package/dist/esm/src/data/transformers/rally.test.d.ts +1 -0
- package/dist/esm/src/data/transformers/rally.test.js +60 -0
- package/dist/esm/src/data/transformers/tactics.js +39 -59
- package/dist/esm/src/data/transformers/tactics.test.js +40 -21
- package/dist/esm/src/service/team/blocking-preference.d.ts +5 -0
- package/dist/esm/src/service/team/blocking-preference.js +1 -0
- package/dist/esm/src/service/team/designated-sub.d.ts +2 -4
- 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/libero-sub.d.ts +0 -4
- package/dist/esm/src/service/team/offensive-preference.d.ts +1 -2
- package/dist/esm/src/service/team/pinch-condition.d.ts +11 -3
- package/dist/esm/src/service/team/pinch-condition.js +9 -4
- package/dist/esm/src/service/team/schemas/designated-sub.z.d.ts +30 -32
- package/dist/esm/src/service/team/schemas/designated-sub.z.js +26 -22
- package/dist/esm/src/service/team/schemas/designated-sub.z.test.js +4 -2
- package/dist/esm/src/service/team/schemas/libero-sub.z.d.ts +15 -34
- package/dist/esm/src/service/team/schemas/libero-sub.z.js +9 -25
- package/dist/esm/src/service/team/schemas/libero-sub.z.test.js +75 -36
- package/dist/esm/src/service/team/schemas/tactics.z.d.ts +39 -39
- package/dist/esm/src/service/team/schemas/tactics.z.js +48 -14
- package/dist/esm/src/service/team/schemas/tactics.z.test.js +81 -8
- package/dist/esm/src/service/team/schemas/team.z.d.ts +38 -38
- package/dist/esm/src/service/team/sub-config-convert.d.ts +13 -0
- package/dist/esm/src/service/team/sub-config-convert.js +85 -0
- package/dist/esm/src/service/team/sub-config-convert.test.d.ts +1 -0
- package/dist/esm/src/service/team/sub-config-convert.test.js +82 -0
- package/dist/esm/src/service/team/tactics.d.ts +5 -0
- package/dist/esm/src/service/team/tactics.js +3 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BoxScore, DataProps, DeclineStatus, Division as _Division, League as _League, Match as _Match, MatchSet as _MatchSet, Player as _Player, PlayerPosition, Qualifier as _Qualifier, QualifierMatch as _QualifierMatch, Rally as _Rally, RallyEvent as _RallyEvent, PointBreakdown, RallyMetrics, Season as _Season, Standing as _Standing, Team as _Team, Tournament as _Tournament, TournamentMatch as _TournamentMatch, National as _National, NationalMatch as _NationalMatch, Country as _Country, CourtPosition, ConditionLogic, EnergyBand,
|
|
1
|
+
import { BoxScore, DataProps, DeclineStatus, Division as _Division, League as _League, Match as _Match, MatchSet as _MatchSet, Player as _Player, PlayerPosition, Qualifier as _Qualifier, QualifierMatch as _QualifierMatch, Rally as _Rally, RallyEvent as _RallyEvent, PointBreakdown, RallyMetrics, Season as _Season, Standing as _Standing, Team as _Team, Tournament as _Tournament, TournamentMatch as _TournamentMatch, National as _National, NationalMatch as _NationalMatch, Country as _Country, CourtPosition, ConditionLogic, EnergyBand, MatchForfeitType, PerformanceStats, PinchCondition, RoleEnum, RotationSystemEnum, SubBackMode, SubBand } from '../service';
|
|
2
2
|
export type Rally = DataProps<_Rally> & {
|
|
3
3
|
homePlayerPosition: PlayerPosition[];
|
|
4
4
|
awayPlayerPosition: PlayerPosition[];
|
|
@@ -81,36 +81,28 @@ export interface StartingLineup {
|
|
|
81
81
|
bench: string[];
|
|
82
82
|
}
|
|
83
83
|
export interface ApiSetSubConfig {
|
|
84
|
-
mode: SubMode;
|
|
85
84
|
benchId?: string;
|
|
86
|
-
fatigueBand?: EnergyBand;
|
|
87
|
-
benchFatigueBand?: EnergyBand;
|
|
88
85
|
conditions?: PinchCondition[];
|
|
89
86
|
conditionLogic?: ConditionLogic;
|
|
90
87
|
pinchServer?: boolean;
|
|
88
|
+
benchFatigueBand?: EnergyBand;
|
|
91
89
|
subBackMode?: SubBackMode;
|
|
92
90
|
subBackConditions?: PinchCondition[];
|
|
93
91
|
subBackConditionLogic?: ConditionLogic;
|
|
94
92
|
}
|
|
95
|
-
export interface ApiDesignatedSub {
|
|
93
|
+
export interface ApiDesignatedSub extends ApiSetSubConfig {
|
|
96
94
|
starterId: string;
|
|
97
|
-
benchId?: string;
|
|
98
|
-
mode: SubMode;
|
|
99
|
-
fatigueBand?: EnergyBand;
|
|
100
|
-
benchFatigueBand?: EnergyBand;
|
|
101
|
-
conditions?: PinchCondition[];
|
|
102
|
-
conditionLogic?: ConditionLogic;
|
|
103
|
-
pinchServer?: boolean;
|
|
104
|
-
subBackMode?: SubBackMode;
|
|
105
|
-
subBackConditions?: PinchCondition[];
|
|
106
|
-
subBackConditionLogic?: ConditionLogic;
|
|
107
95
|
sets?: ApiSetSubConfig[];
|
|
108
96
|
}
|
|
109
97
|
export interface ApiOffensivePreference {
|
|
110
98
|
rotation: number;
|
|
111
|
-
|
|
99
|
+
weights: Record<string, number>;
|
|
112
100
|
tempos?: Record<string, 'FAST' | 'HIGH'>;
|
|
113
101
|
}
|
|
102
|
+
export interface ApiBlockingPreference {
|
|
103
|
+
rotation: number;
|
|
104
|
+
targets: Record<string, RoleEnum>;
|
|
105
|
+
}
|
|
114
106
|
export interface ApiSystemSet {
|
|
115
107
|
rotationSystem: RotationSystemEnum;
|
|
116
108
|
designatedSetters: string[];
|
|
@@ -126,8 +118,6 @@ export interface ApiLiberoInjury {
|
|
|
126
118
|
inMatchDesignateId?: string;
|
|
127
119
|
}
|
|
128
120
|
export interface ApiLiberoSetSubConfig {
|
|
129
|
-
mode: LiberoSubMode;
|
|
130
|
-
fatigueBand?: EnergyBand;
|
|
131
121
|
conditions?: PinchCondition[];
|
|
132
122
|
conditionLogic?: ConditionLogic;
|
|
133
123
|
}
|
|
@@ -148,6 +138,8 @@ export interface Tactics {
|
|
|
148
138
|
offensivePreferences: ApiOffensivePreference[];
|
|
149
139
|
systemSets?: ApiSystemSet[];
|
|
150
140
|
offensivePreferenceSets?: ApiOffensivePreference[][];
|
|
141
|
+
blockingPreferences: ApiBlockingPreference[];
|
|
142
|
+
blockingPreferenceSets?: ApiBlockingPreference[][];
|
|
151
143
|
replaceKnockedImmediately?: Record<string, boolean>;
|
|
152
144
|
injuryReplacements?: ApiInjuryReplacement[];
|
|
153
145
|
liberoInjury?: ApiLiberoInjury;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model, Optional } from 'sequelize';
|
|
3
3
|
import { PlayerId, TeamId, TeamModel } from '.';
|
|
4
|
-
import { ConditionLogic, CourtPosition, EnergyBand,
|
|
4
|
+
import { ConditionLogic, CourtPosition, EnergyBand, PinchCondition, RoleEnum, RotationSystemEnum, SubBackMode, SubBand, SubMode } from '../../service';
|
|
5
5
|
export interface TacticsLineupAttributes {
|
|
6
6
|
[CourtPosition.LIBERO_ZONE]?: PlayerId;
|
|
7
7
|
[CourtPosition.LEFT_BACK]: PlayerId;
|
|
@@ -13,37 +13,31 @@ export interface TacticsLineupAttributes {
|
|
|
13
13
|
bench: PlayerId[];
|
|
14
14
|
}
|
|
15
15
|
export interface SetSubConfigAttributes {
|
|
16
|
-
mode: SubMode;
|
|
17
16
|
benchId?: PlayerId;
|
|
18
|
-
fatigueBand?: EnergyBand;
|
|
19
|
-
benchFatigueBand?: EnergyBand;
|
|
20
17
|
conditions?: PinchCondition[];
|
|
21
18
|
conditionLogic?: ConditionLogic;
|
|
22
19
|
pinchServer?: boolean;
|
|
20
|
+
benchFatigueBand?: EnergyBand;
|
|
23
21
|
subBackMode?: SubBackMode;
|
|
24
22
|
subBackConditions?: PinchCondition[];
|
|
25
23
|
subBackConditionLogic?: ConditionLogic;
|
|
24
|
+
mode?: SubMode;
|
|
25
|
+
fatigueBand?: SubBand;
|
|
26
26
|
}
|
|
27
|
-
export interface DesignatedSubAttributes {
|
|
27
|
+
export interface DesignatedSubAttributes extends SetSubConfigAttributes {
|
|
28
28
|
starterId: PlayerId;
|
|
29
|
-
benchId?: PlayerId;
|
|
30
|
-
mode?: SubMode;
|
|
31
29
|
isPinchServer?: boolean;
|
|
32
|
-
fatigueBand?: SubBand;
|
|
33
|
-
benchFatigueBand?: EnergyBand;
|
|
34
|
-
conditions?: PinchCondition[];
|
|
35
|
-
conditionLogic?: ConditionLogic;
|
|
36
|
-
pinchServer?: boolean;
|
|
37
|
-
subBackMode?: SubBackMode;
|
|
38
|
-
subBackConditions?: PinchCondition[];
|
|
39
|
-
subBackConditionLogic?: ConditionLogic;
|
|
40
30
|
sets?: SetSubConfigAttributes[];
|
|
41
31
|
}
|
|
42
32
|
export interface OffensivePreferenceAttributes {
|
|
43
33
|
rotation: number;
|
|
44
|
-
|
|
34
|
+
weights: Record<PlayerId, number>;
|
|
45
35
|
tempos?: Record<PlayerId, 'FAST' | 'HIGH'>;
|
|
46
36
|
}
|
|
37
|
+
export interface BlockingPreferenceAttributes {
|
|
38
|
+
rotation: number;
|
|
39
|
+
targets: Record<PlayerId, RoleEnum>;
|
|
40
|
+
}
|
|
47
41
|
export interface SystemSetAttributes {
|
|
48
42
|
rotationSystem: RotationSystemEnum;
|
|
49
43
|
designatedSetters: PlayerId[];
|
|
@@ -59,10 +53,10 @@ export interface LiberoInjuryAttributes {
|
|
|
59
53
|
inMatchDesignateId?: PlayerId;
|
|
60
54
|
}
|
|
61
55
|
export interface LiberoSetSubConfigAttributes {
|
|
62
|
-
mode: LiberoSubMode;
|
|
63
|
-
fatigueBand?: EnergyBand;
|
|
64
56
|
conditions?: PinchCondition[];
|
|
65
57
|
conditionLogic?: ConditionLogic;
|
|
58
|
+
mode?: string;
|
|
59
|
+
fatigueBand?: EnergyBand;
|
|
66
60
|
}
|
|
67
61
|
export interface LiberoSubConfigAttributes extends LiberoSetSubConfigAttributes {
|
|
68
62
|
sets?: LiberoSetSubConfigAttributes[];
|
|
@@ -85,10 +79,12 @@ export interface TacticsAttributes {
|
|
|
85
79
|
replace_knocked_immediately?: Record<PlayerId, boolean>;
|
|
86
80
|
injury_replacements?: InjuryReplacementAttributes[];
|
|
87
81
|
libero_injury?: LiberoInjuryAttributes;
|
|
82
|
+
blocking_preferences: BlockingPreferenceAttributes[];
|
|
83
|
+
blocking_preference_sets?: BlockingPreferenceAttributes[][];
|
|
88
84
|
}
|
|
89
85
|
export type TacticsPk = 'team_id';
|
|
90
86
|
export type TacticsId = TacticsModel[TacticsPk];
|
|
91
|
-
export type TacticsOptionalAttributes = 'lineup' | 'libero_replacements' | 'receive_rotation_offset' | 'designated_subs' | 'substitution_band' | 'second_libero' | 'libero_sub' | 'libero_replacement_sets' | 'rotation_system' | 'designated_setters' | 'offensive_preferences' | 'system_sets' | 'offensive_preference_sets' | 'replace_knocked_immediately' | 'injury_replacements' | 'libero_injury';
|
|
87
|
+
export type TacticsOptionalAttributes = 'lineup' | 'libero_replacements' | 'receive_rotation_offset' | 'designated_subs' | 'substitution_band' | 'second_libero' | 'libero_sub' | 'libero_replacement_sets' | 'rotation_system' | 'designated_setters' | 'offensive_preferences' | 'system_sets' | 'offensive_preference_sets' | 'replace_knocked_immediately' | 'injury_replacements' | 'libero_injury' | 'blocking_preferences' | 'blocking_preference_sets';
|
|
92
88
|
export type TacticsCreationAttributes = Optional<TacticsAttributes, TacticsOptionalAttributes>;
|
|
93
89
|
export declare class TacticsModel extends Model<TacticsAttributes, TacticsCreationAttributes> implements TacticsAttributes {
|
|
94
90
|
team_id: string;
|
|
@@ -108,6 +104,8 @@ export declare class TacticsModel extends Model<TacticsAttributes, TacticsCreati
|
|
|
108
104
|
replace_knocked_immediately?: Record<PlayerId, boolean>;
|
|
109
105
|
injury_replacements?: InjuryReplacementAttributes[];
|
|
110
106
|
libero_injury?: LiberoInjuryAttributes;
|
|
107
|
+
blocking_preferences: BlockingPreferenceAttributes[];
|
|
108
|
+
blocking_preference_sets?: BlockingPreferenceAttributes[][];
|
|
111
109
|
team: TeamModel;
|
|
112
110
|
getTeam: Sequelize.BelongsToGetAssociationMixin<TeamModel>;
|
|
113
111
|
setTeam: Sequelize.BelongsToSetAssociationMixin<TeamModel, TeamId>;
|
|
@@ -86,6 +86,15 @@ class TacticsModel extends sequelize_1.Model {
|
|
|
86
86
|
libero_injury: {
|
|
87
87
|
type: sequelize_1.DataTypes.JSONB,
|
|
88
88
|
allowNull: true
|
|
89
|
+
},
|
|
90
|
+
blocking_preferences: {
|
|
91
|
+
type: sequelize_1.DataTypes.JSONB,
|
|
92
|
+
allowNull: false,
|
|
93
|
+
defaultValue: []
|
|
94
|
+
},
|
|
95
|
+
blocking_preference_sets: {
|
|
96
|
+
type: sequelize_1.DataTypes.JSONB,
|
|
97
|
+
allowNull: true
|
|
89
98
|
}
|
|
90
99
|
}, {
|
|
91
100
|
sequelize,
|
|
@@ -150,7 +150,16 @@ function starterAt(tactics, zone) {
|
|
|
150
150
|
(0, globals_1.expect)(back.lineup).toEqual(full.lineup);
|
|
151
151
|
(0, globals_1.expect)(back.libero_replacements).toEqual(full.libero_replacements);
|
|
152
152
|
(0, globals_1.expect)(back.receive_rotation_offset).toBe(true);
|
|
153
|
-
|
|
153
|
+
// The dto path converts legacy mode-shaped subs to the unified condition engine, so the round-trip lands
|
|
154
|
+
// in the converted (unified) shape rather than the legacy input.
|
|
155
|
+
(0, globals_1.expect)(back.designated_subs).toEqual([{
|
|
156
|
+
starterId: ids[0],
|
|
157
|
+
conditions: [{ type: 'FATIGUE', band: 'WORN' }],
|
|
158
|
+
conditionLogic: 'ALL',
|
|
159
|
+
pinchServer: false,
|
|
160
|
+
subBackMode: 'FATIGUE',
|
|
161
|
+
sets: [{ conditions: [] }]
|
|
162
|
+
}]);
|
|
154
163
|
(0, globals_1.expect)(back.libero_replacement_sets).toEqual(full.libero_replacement_sets);
|
|
155
164
|
(0, globals_1.expect)(back.rotation_system).toBe('5-1');
|
|
156
165
|
(0, globals_1.expect)(back.designated_setters).toEqual(full.designated_setters);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Block, LiberoReplacement, RallyEvent, Reception, Serve, Set, Spike, Substitution } from '../../service';
|
|
1
|
+
import { Block, FreeBall, LiberoReplacement, RallyEvent, Reception, Serve, Set, Spike, Substitution } from '../../service';
|
|
2
2
|
export interface CompactEvent {
|
|
3
3
|
p: number;
|
|
4
4
|
e: number;
|
|
@@ -21,4 +21,5 @@ export declare function transformToReception(event: CompactEvent, roster: string
|
|
|
21
21
|
export declare function transformToServe(event: CompactEvent, roster: string[]): Serve;
|
|
22
22
|
export declare function transformToSet(event: CompactEvent, roster: string[]): Set;
|
|
23
23
|
export declare function transformToSpike(event: CompactEvent, roster: string[]): Spike;
|
|
24
|
+
export declare function transformToFreeBall(event: CompactEvent, roster: string[]): FreeBall;
|
|
24
25
|
export declare function transformToSubstitution(event: CompactEvent, roster: string[]): Substitution;
|
|
@@ -7,6 +7,7 @@ exports.transformToReception = transformToReception;
|
|
|
7
7
|
exports.transformToServe = transformToServe;
|
|
8
8
|
exports.transformToSet = transformToSet;
|
|
9
9
|
exports.transformToSpike = transformToSpike;
|
|
10
|
+
exports.transformToFreeBall = transformToFreeBall;
|
|
10
11
|
exports.transformToSubstitution = transformToSubstitution;
|
|
11
12
|
const service_1 = require("../../service");
|
|
12
13
|
// Incident packing for the compact key 'i': values below 10 are injury severities, 10+ are knock tiers.
|
|
@@ -118,6 +119,17 @@ function transformToSpike(event, roster) {
|
|
|
118
119
|
incident: incidentFromCompact(event.i, event.h, roster)
|
|
119
120
|
});
|
|
120
121
|
}
|
|
122
|
+
// FreeBall (Last Resort save) is a plain InPlayEvent with no incident of its own, so it decodes from f/t/a/s
|
|
123
|
+
// exactly like a spike minus the incident. Must stay in lockstep with the case 7 branch in rally.ts.
|
|
124
|
+
function transformToFreeBall(event, roster) {
|
|
125
|
+
return service_1.FreeBall.create({
|
|
126
|
+
failure: event.f,
|
|
127
|
+
type: event.t,
|
|
128
|
+
playerId: roster[event.p],
|
|
129
|
+
target: event.a,
|
|
130
|
+
score: event.s
|
|
131
|
+
});
|
|
132
|
+
}
|
|
121
133
|
function transformToSubstitution(event, roster) {
|
|
122
134
|
return service_1.Substitution.create({
|
|
123
135
|
playerId: roster[event.p],
|
|
@@ -61,6 +61,7 @@ function decodeCompactEvent(event, roster) {
|
|
|
61
61
|
case 4: return (0, rally_event_1.transformToSet)(event, roster);
|
|
62
62
|
case 5: return (0, rally_event_1.transformToSpike)(event, roster);
|
|
63
63
|
case 6: return (0, rally_event_1.transformToBlock)(event, roster);
|
|
64
|
+
case 7: return (0, rally_event_1.transformToFreeBall)(event, roster);
|
|
64
65
|
default: throw new Error(`UNKNOWN_EVENT_TYPE: ${String(event.e)}`);
|
|
65
66
|
}
|
|
66
67
|
}
|
|
@@ -73,6 +74,7 @@ function decodeLegacyEvent(event) {
|
|
|
73
74
|
case 4: return service_1.Set.create({ failure: event.f, type: event.t, playerId: event.p, target: event.a, score: event.s });
|
|
74
75
|
case 5: return service_1.Spike.create({ failure: event.f, type: event.t, playerId: event.p, target: event.a, score: event.s });
|
|
75
76
|
case 6: return service_1.Block.create({ failure: event.f, type: event.t, playerId: event.p, target: event.a, blockers: event.b ?? [], score: event.s });
|
|
77
|
+
case 7: return service_1.FreeBall.create({ failure: event.f, type: event.t, playerId: event.p, target: event.a, score: event.s });
|
|
76
78
|
default: throw new Error(`UNKNOWN_EVENT_TYPE: ${String(event.e)}`);
|
|
77
79
|
}
|
|
78
80
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const globals_1 = require("@jest/globals");
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const service_1 = require("../../service");
|
|
6
|
+
const rally_1 = require("./rally");
|
|
7
|
+
// End-to-end rally round trip (encode -> bytea -> decode) exercising the decodeCompactEvent switch, with one
|
|
8
|
+
// event of EVERY EventTypeEnum member. This is the guard that would have caught the FREE_BALL decoder gap: the
|
|
9
|
+
// encoder is generic (out.e = evt.eventType) but the decoder is a hardcoded switch, so a new event type that is
|
|
10
|
+
// not wired into the switch throws UNKNOWN_EVENT_TYPE here. The coverage test forces new members into this list.
|
|
11
|
+
(0, globals_1.describe)('rally compact round trip — every event type', () => {
|
|
12
|
+
const pA = (0, uuid_1.v4)();
|
|
13
|
+
const pB = (0, uuid_1.v4)();
|
|
14
|
+
const pC = (0, uuid_1.v4)();
|
|
15
|
+
const setId = (0, uuid_1.v4)();
|
|
16
|
+
const events = [
|
|
17
|
+
service_1.LiberoReplacement.create({ playerId: pA, libero: pB, type: service_1.LiberoReplacementTypeEnum.LIBERO_IN }),
|
|
18
|
+
service_1.Substitution.create({ playerId: pA, playerOut: pC, injury: true }),
|
|
19
|
+
service_1.Serve.create({ playerId: pA, target: 6, score: 55, failure: service_1.ServeFailureEnum.NO_FAILURE, type: service_1.ServeTypeEnum.JUMP_TOPSPIN }),
|
|
20
|
+
service_1.Reception.create({ playerId: pB, target: 5, score: 50, failure: service_1.ReceptionFailureEnum.NO_FAILURE, type: service_1.ReceptionTypeEnum.DIG }),
|
|
21
|
+
service_1.Set.create({ playerId: pC, target: 3, score: 48, failure: service_1.SetFailureEnum.NO_FAILURE, type: service_1.SetTypeEnum.OVERHAND, tempo: service_1.SetTempoEnum.FIRST }),
|
|
22
|
+
service_1.Spike.create({ playerId: pA, target: 4, score: 62.5, failure: service_1.SpikeFailureEnum.NO_FAILURE, type: service_1.SpikeTypeEnum.CROSS_SHOT }),
|
|
23
|
+
service_1.Block.create({ playerId: pB, blockers: [pB, pC], target: 8, score: 48, failure: service_1.BlockFailureEnum.NO_FAILURE, type: service_1.BlockTypeEnum.DOUBLE }),
|
|
24
|
+
service_1.FreeBall.create({ playerId: pC, target: 6, score: 45, failure: service_1.FreeBallFailureEnum.NO_FAILURE, type: service_1.FreeBallTypeEnum.OVER })
|
|
25
|
+
];
|
|
26
|
+
const rally = service_1.Rally.create({ id: (0, uuid_1.v4)(), order: 0, servingTeamId: (0, uuid_1.v4)(), events });
|
|
27
|
+
(0, globals_1.it)('covers every EventTypeEnum member (adding a new event type must extend this list)', () => {
|
|
28
|
+
const numericTypes = Object.values(service_1.EventTypeEnum).filter((v) => typeof v === 'number');
|
|
29
|
+
const present = new Set(events.map(e => e.eventType));
|
|
30
|
+
for (const t of numericTypes)
|
|
31
|
+
(0, globals_1.expect)(present.has(t)).toBe(true);
|
|
32
|
+
(0, globals_1.expect)(present.size).toBe(numericTypes.length);
|
|
33
|
+
});
|
|
34
|
+
(0, globals_1.it)('encodes then decodes every event type back to an equal event (guards the decoder switch)', () => {
|
|
35
|
+
const attrs = (0, rally_1.transformFromRally)(rally, setId);
|
|
36
|
+
const decoded = (0, rally_1.transformToRally)(attrs);
|
|
37
|
+
(0, globals_1.expect)(decoded.events).toHaveLength(events.length);
|
|
38
|
+
(0, globals_1.expect)(decoded.events.map(e => e.eventType)).toEqual(events.map(e => e.eventType));
|
|
39
|
+
const [lib, sub, serve, rec, set, spike, block, free] = decoded.events;
|
|
40
|
+
(0, globals_1.expect)(lib.playerId).toBe(pA);
|
|
41
|
+
(0, globals_1.expect)(lib.libero).toBe(pB);
|
|
42
|
+
(0, globals_1.expect)(lib.type).toBe(service_1.LiberoReplacementTypeEnum.LIBERO_IN);
|
|
43
|
+
(0, globals_1.expect)(sub.playerOut).toBe(pC);
|
|
44
|
+
(0, globals_1.expect)(sub.injury).toBe(true);
|
|
45
|
+
(0, globals_1.expect)(serve.target).toBe(6);
|
|
46
|
+
(0, globals_1.expect)(serve.score).toBe(55);
|
|
47
|
+
(0, globals_1.expect)(serve.type).toBe(service_1.ServeTypeEnum.JUMP_TOPSPIN);
|
|
48
|
+
(0, globals_1.expect)(rec.target).toBe(5);
|
|
49
|
+
(0, globals_1.expect)(rec.type).toBe(service_1.ReceptionTypeEnum.DIG);
|
|
50
|
+
(0, globals_1.expect)(set.type).toBe(service_1.SetTypeEnum.OVERHAND);
|
|
51
|
+
(0, globals_1.expect)(set.tempo).toBe(service_1.SetTempoEnum.FIRST);
|
|
52
|
+
(0, globals_1.expect)(spike.type).toBe(service_1.SpikeTypeEnum.CROSS_SHOT);
|
|
53
|
+
(0, globals_1.expect)(spike.score).toBe(62.5);
|
|
54
|
+
(0, globals_1.expect)(block.type).toBe(service_1.BlockTypeEnum.DOUBLE);
|
|
55
|
+
(0, globals_1.expect)(block.blockers).toEqual([pB, pC]);
|
|
56
|
+
(0, globals_1.expect)(free.playerId).toBe(pC);
|
|
57
|
+
(0, globals_1.expect)(free.target).toBe(6);
|
|
58
|
+
(0, globals_1.expect)(free.score).toBe(45);
|
|
59
|
+
(0, globals_1.expect)(free.type).toBe(service_1.FreeBallTypeEnum.OVER);
|
|
60
|
+
(0, globals_1.expect)(free.failure).toBe(service_1.FreeBallFailureEnum.NO_FAILURE);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -5,24 +5,9 @@ exports.transformFromTactics = transformToAttributes;
|
|
|
5
5
|
exports.tacticsColumnsToApiDto = tacticsColumnsToApiDto;
|
|
6
6
|
exports.apiTacticsConfigToTacticsAttributes = apiTacticsConfigToAttributes;
|
|
7
7
|
const service_1 = require("../../service");
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
function subModeFromAttributes(d) {
|
|
12
|
-
if (d.mode != null)
|
|
13
|
-
return d.mode;
|
|
14
|
-
if (d.isPinchServer === true)
|
|
15
|
-
return 'PINCH';
|
|
16
|
-
if (d.fatigueBand === 'NEVER')
|
|
17
|
-
return 'NEVER';
|
|
18
|
-
return 'FATIGUE';
|
|
19
|
-
}
|
|
20
|
-
// pinchServer only applies to PINCH ("Conditions") mode. A LEGACY PINCH row (no flag) defaults to true so
|
|
21
|
-
// existing pinch servers keep serve-and-return behavior; a new conditional sub persists an explicit false. This
|
|
22
|
-
// default must resolve identically on every READ path (both transformToObject and tacticsColumnsToApiDto).
|
|
23
|
-
function effectivePinchServer(mode, pinchServer) {
|
|
24
|
-
return mode === 'PINCH' ? (pinchServer ?? true) : undefined;
|
|
25
|
-
}
|
|
8
|
+
// Unified condition engine (owner 2026-07-11): the READ path passes legacy fields (mode / fatigueBand /
|
|
9
|
+
// isPinchServer) through RAW; the schema preprocess in Tactics.create converts every legacy shape (see
|
|
10
|
+
// service/team/sub-config-convert.ts). The WRITE path persists only the unified shape.
|
|
26
11
|
function findPlayer(id, roster) {
|
|
27
12
|
const player = roster.find((p) => p.id === id);
|
|
28
13
|
if (player == null)
|
|
@@ -66,23 +51,19 @@ function transformToAttributes(tactics, teamId) {
|
|
|
66
51
|
designated_subs: tactics.designatedSubs.map(ds => ({
|
|
67
52
|
starterId: ds.starter.id,
|
|
68
53
|
benchId: ds.bench?.id,
|
|
69
|
-
mode: ds.mode,
|
|
70
|
-
fatigueBand: ds.fatigueBand,
|
|
71
|
-
benchFatigueBand: ds.benchFatigueBand,
|
|
72
54
|
conditions: ds.conditions,
|
|
73
55
|
conditionLogic: ds.conditionLogic,
|
|
74
56
|
pinchServer: ds.pinchServer,
|
|
57
|
+
benchFatigueBand: ds.benchFatigueBand,
|
|
75
58
|
subBackMode: ds.subBackMode,
|
|
76
59
|
subBackConditions: ds.subBackConditions,
|
|
77
60
|
subBackConditionLogic: ds.subBackConditionLogic,
|
|
78
61
|
sets: ds.sets?.map(s => ({
|
|
79
|
-
mode: s.mode,
|
|
80
62
|
benchId: s.bench?.id,
|
|
81
|
-
fatigueBand: s.fatigueBand,
|
|
82
|
-
benchFatigueBand: s.benchFatigueBand,
|
|
83
63
|
conditions: s.conditions,
|
|
84
64
|
conditionLogic: s.conditionLogic,
|
|
85
65
|
pinchServer: s.pinchServer,
|
|
66
|
+
benchFatigueBand: s.benchFatigueBand,
|
|
86
67
|
subBackMode: s.subBackMode,
|
|
87
68
|
subBackConditions: s.subBackConditions,
|
|
88
69
|
subBackConditionLogic: s.subBackConditionLogic
|
|
@@ -92,7 +73,7 @@ function transformToAttributes(tactics, teamId) {
|
|
|
92
73
|
designated_setters: tactics.designatedSetters.map((s) => s.id),
|
|
93
74
|
offensive_preferences: tactics.offensivePreferences.map(p => ({
|
|
94
75
|
rotation: p.rotation,
|
|
95
|
-
|
|
76
|
+
weights: p.weights,
|
|
96
77
|
tempos: p.tempos
|
|
97
78
|
})),
|
|
98
79
|
system_sets: tactics.systemSets?.map(s => ({
|
|
@@ -101,9 +82,11 @@ function transformToAttributes(tactics, teamId) {
|
|
|
101
82
|
})),
|
|
102
83
|
offensive_preference_sets: tactics.offensivePreferenceSets?.map(prefs => prefs.map(p => ({
|
|
103
84
|
rotation: p.rotation,
|
|
104
|
-
|
|
85
|
+
weights: p.weights,
|
|
105
86
|
tempos: p.tempos
|
|
106
87
|
}))),
|
|
88
|
+
blocking_preferences: tactics.blockingPreferences.map(p => ({ rotation: p.rotation, targets: p.targets })),
|
|
89
|
+
blocking_preference_sets: tactics.blockingPreferenceSets?.map(prefs => prefs.map(p => ({ rotation: p.rotation, targets: p.targets }))),
|
|
107
90
|
replace_knocked_immediately: tactics.replaceKnockedImmediately,
|
|
108
91
|
injury_replacements: tactics.injuryReplacements.map(ir => ({
|
|
109
92
|
starterId: ir.starter.id,
|
|
@@ -163,15 +146,19 @@ function transformToObject(model, roster) {
|
|
|
163
146
|
secondLibero,
|
|
164
147
|
liberoSub: secondLibero != null ? (model.libero_sub ?? undefined) : undefined,
|
|
165
148
|
liberoReplacementSets,
|
|
149
|
+
// Legacy fields (mode / fatigueBand / isPinchServer) pass through RAW: the DesignatedSubSchema preprocess
|
|
150
|
+
// inside Tactics.create converts every legacy shape (mode-era AND isPinchServer-era rows) to the unified
|
|
151
|
+
// condition engine. Only the player references are resolved here.
|
|
166
152
|
designatedSubs: (model.designated_subs ?? []).map(d => ({
|
|
167
153
|
starter: findPlayer(d.starterId, roster),
|
|
168
154
|
bench: d.benchId != null ? findPlayer(d.benchId, roster) : undefined,
|
|
169
|
-
mode:
|
|
170
|
-
|
|
155
|
+
mode: d.mode,
|
|
156
|
+
isPinchServer: d.isPinchServer,
|
|
157
|
+
fatigueBand: d.fatigueBand,
|
|
171
158
|
benchFatigueBand: d.benchFatigueBand,
|
|
172
159
|
conditions: d.conditions,
|
|
173
160
|
conditionLogic: d.conditionLogic,
|
|
174
|
-
pinchServer:
|
|
161
|
+
pinchServer: d.pinchServer,
|
|
175
162
|
subBackMode: d.subBackMode,
|
|
176
163
|
subBackConditions: d.subBackConditions,
|
|
177
164
|
subBackConditionLogic: d.subBackConditionLogic,
|
|
@@ -182,7 +169,7 @@ function transformToObject(model, roster) {
|
|
|
182
169
|
benchFatigueBand: s.benchFatigueBand,
|
|
183
170
|
conditions: s.conditions,
|
|
184
171
|
conditionLogic: s.conditionLogic,
|
|
185
|
-
pinchServer:
|
|
172
|
+
pinchServer: s.pinchServer,
|
|
186
173
|
subBackMode: s.subBackMode,
|
|
187
174
|
subBackConditions: s.subBackConditions,
|
|
188
175
|
subBackConditionLogic: s.subBackConditionLogic
|
|
@@ -192,7 +179,7 @@ function transformToObject(model, roster) {
|
|
|
192
179
|
designatedSetters: (model.designated_setters ?? []).map((id) => findPlayer(id, roster)),
|
|
193
180
|
offensivePreferences: (model.offensive_preferences ?? []).map(p => ({
|
|
194
181
|
rotation: p.rotation,
|
|
195
|
-
|
|
182
|
+
weights: p.weights,
|
|
196
183
|
tempos: p.tempos
|
|
197
184
|
})),
|
|
198
185
|
systemSets: model.system_sets?.map(s => ({
|
|
@@ -201,9 +188,11 @@ function transformToObject(model, roster) {
|
|
|
201
188
|
})),
|
|
202
189
|
offensivePreferenceSets: model.offensive_preference_sets?.map(prefs => prefs.map(p => ({
|
|
203
190
|
rotation: p.rotation,
|
|
204
|
-
|
|
191
|
+
weights: p.weights,
|
|
205
192
|
tempos: p.tempos
|
|
206
193
|
}))),
|
|
194
|
+
blockingPreferences: (model.blocking_preferences ?? []).map(p => ({ rotation: p.rotation, targets: p.targets })),
|
|
195
|
+
blockingPreferenceSets: model.blocking_preference_sets?.map(prefs => prefs.map(p => ({ rotation: p.rotation, targets: p.targets }))),
|
|
207
196
|
// LENIENT: keep only boolean entries keyed by a court starter or, when a second libero exists, the starting
|
|
208
197
|
// libero (the libero knock toggle is an L2-only feature, owner 2026-07-06) so stale jsonb (an ex-starter's
|
|
209
198
|
// key, a non-boolean value, a libero key left after the L2 was removed) can never fail schema validation
|
|
@@ -328,38 +317,27 @@ function tacticsColumnsToApiDto(model) {
|
|
|
328
317
|
receiveRotationOffset: model.receive_rotation_offset,
|
|
329
318
|
substitutionBand: model.substitution_band,
|
|
330
319
|
secondLibero: validSecondLibero,
|
|
331
|
-
|
|
320
|
+
// The API surfaces the UNIFIED condition-engine shape: legacy rows (mode-era / isPinchServer-era) convert
|
|
321
|
+
// here via the same service converters the schema preprocess uses, so clients never see a mode.
|
|
322
|
+
liberoSub: validSecondLibero != null
|
|
323
|
+
? (model.libero_sub != null ? (0, service_1.convertLegacyLiberoSubConfig)(model.libero_sub) : undefined)
|
|
324
|
+
: undefined,
|
|
332
325
|
liberoReplacementSets: validLiberoReplacementSets,
|
|
333
|
-
designatedSubs: (model.designated_subs ?? []).map(d =>
|
|
334
|
-
starterId
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
pinchServer: effectivePinchServer(subModeFromAttributes(d), d.pinchServer),
|
|
342
|
-
subBackMode: d.subBackMode,
|
|
343
|
-
subBackConditions: d.subBackConditions,
|
|
344
|
-
subBackConditionLogic: d.subBackConditionLogic,
|
|
345
|
-
sets: d.sets?.map(s => ({
|
|
346
|
-
mode: s.mode,
|
|
347
|
-
benchId: s.benchId,
|
|
348
|
-
fatigueBand: s.fatigueBand,
|
|
349
|
-
benchFatigueBand: s.benchFatigueBand,
|
|
350
|
-
conditions: s.conditions,
|
|
351
|
-
conditionLogic: s.conditionLogic,
|
|
352
|
-
pinchServer: effectivePinchServer(s.mode, s.pinchServer),
|
|
353
|
-
subBackMode: s.subBackMode,
|
|
354
|
-
subBackConditions: s.subBackConditions,
|
|
355
|
-
subBackConditionLogic: s.subBackConditionLogic
|
|
356
|
-
}))
|
|
357
|
-
})),
|
|
326
|
+
designatedSubs: (model.designated_subs ?? []).map(d => {
|
|
327
|
+
const { starterId, sets, ...cfg } = d;
|
|
328
|
+
return {
|
|
329
|
+
...(0, service_1.convertLegacySetSubConfig)(cfg),
|
|
330
|
+
starterId,
|
|
331
|
+
sets: sets?.map(s => (0, service_1.convertLegacySetSubConfig)(s))
|
|
332
|
+
};
|
|
333
|
+
}),
|
|
358
334
|
rotationSystem: model.rotation_system,
|
|
359
335
|
designatedSetters: model.designated_setters,
|
|
360
336
|
offensivePreferences: model.offensive_preferences,
|
|
361
337
|
systemSets: model.system_sets,
|
|
362
338
|
offensivePreferenceSets: model.offensive_preference_sets,
|
|
339
|
+
blockingPreferences: model.blocking_preferences,
|
|
340
|
+
blockingPreferenceSets: model.blocking_preference_sets,
|
|
363
341
|
// Same stale-data policy as the heals below: only boolean entries keyed by a court starter or, when a second
|
|
364
342
|
// libero exists, the starting libero (the libero knock toggle is an L2-only feature, owner 2026-07-06)
|
|
365
343
|
// survive; an empty map surfaces as absent (missing key = ON).
|
|
@@ -465,6 +443,8 @@ function apiTacticsConfigToAttributes(config, teamId) {
|
|
|
465
443
|
offensive_preferences: config.offensivePreferences,
|
|
466
444
|
system_sets: config.systemSets,
|
|
467
445
|
offensive_preference_sets: config.offensivePreferenceSets,
|
|
446
|
+
blocking_preferences: config.blockingPreferences ?? [],
|
|
447
|
+
blocking_preference_sets: config.blockingPreferenceSets,
|
|
468
448
|
replace_knocked_immediately: config.replaceKnockedImmediately,
|
|
469
449
|
injury_replacements: config.injuryReplacements,
|
|
470
450
|
libero_injury: config.liberoInjury
|