volleyballsimtypes 0.0.463 → 0.0.465
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 +13 -1
- package/dist/cjs/src/data/init-models.js +8 -0
- package/dist/cjs/src/data/models/currency-transaction.d.ts +4 -2
- package/dist/cjs/src/data/models/currency-transaction.js +2 -0
- package/dist/cjs/src/data/models/index.d.ts +2 -0
- package/dist/cjs/src/data/models/index.js +2 -0
- package/dist/cjs/src/data/models/match-set.d.ts +2 -0
- package/dist/cjs/src/data/models/match-set.js +5 -0
- package/dist/cjs/src/data/models/match.d.ts +3 -1
- package/dist/cjs/src/data/models/match.js +4 -0
- package/dist/cjs/src/data/models/physician.d.ts +25 -0
- package/dist/cjs/src/data/models/physician.js +57 -0
- package/dist/cjs/src/data/models/physiotherapist.d.ts +25 -0
- package/dist/cjs/src/data/models/physiotherapist.js +57 -0
- package/dist/cjs/src/data/models/player.d.ts +8 -0
- package/dist/cjs/src/data/models/player.js +17 -0
- package/dist/cjs/src/data/models/tactics.d.ts +10 -1
- package/dist/cjs/src/data/models/tactics.js +9 -0
- package/dist/cjs/src/data/transformers/lineup-preset.js +7 -1
- package/dist/cjs/src/data/transformers/lineup-preset.test.js +15 -2
- package/dist/cjs/src/data/transformers/match-set.js +2 -0
- package/dist/cjs/src/data/transformers/match.js +6 -2
- package/dist/cjs/src/data/transformers/player.js +15 -1
- package/dist/cjs/src/data/transformers/rally-event-injury.test.d.ts +1 -0
- package/dist/cjs/src/data/transformers/rally-event-injury.test.js +33 -0
- package/dist/cjs/src/data/transformers/rally-event.d.ts +1 -0
- package/dist/cjs/src/data/transformers/rally-event.js +4 -1
- package/dist/cjs/src/data/transformers/tactics.js +83 -4
- package/dist/cjs/src/service/event/schemas/substitution.z.d.ts +1 -0
- package/dist/cjs/src/service/event/schemas/substitution.z.js +2 -1
- package/dist/cjs/src/service/event/substitution.d.ts +1 -0
- package/dist/cjs/src/service/event/substitution.js +4 -2
- package/dist/cjs/src/service/match/match-set-forfeit.test.d.ts +1 -0
- package/dist/cjs/src/service/match/match-set-forfeit.test.js +76 -0
- package/dist/cjs/src/service/match/match-set.d.ts +8 -0
- package/dist/cjs/src/service/match/match-set.js +23 -1
- package/dist/cjs/src/service/match/match.d.ts +2 -0
- package/dist/cjs/src/service/match/match.js +2 -1
- package/dist/cjs/src/service/match/schemas/match-set.z.d.ts +1 -0
- package/dist/cjs/src/service/match/schemas/match-set.z.js +30 -2
- package/dist/cjs/src/service/match/schemas/match.z.d.ts +4 -0
- package/dist/cjs/src/service/match/schemas/match.z.js +4 -1
- package/dist/cjs/src/service/player/index.d.ts +1 -0
- package/dist/cjs/src/service/player/index.js +1 -0
- package/dist/cjs/src/service/player/injury.d.ts +14 -0
- package/dist/cjs/src/service/player/injury.js +39 -0
- package/dist/cjs/src/service/player/injury.test.d.ts +1 -0
- package/dist/cjs/src/service/player/injury.test.js +78 -0
- package/dist/cjs/src/service/player/player-generator.js +3 -1
- package/dist/cjs/src/service/player/player.d.ts +3 -0
- package/dist/cjs/src/service/player/player.js +3 -1
- package/dist/cjs/src/service/player/schemas/player.z.d.ts +6 -0
- package/dist/cjs/src/service/player/schemas/player.z.js +7 -0
- package/dist/cjs/src/service/team/index.d.ts +1 -0
- package/dist/cjs/src/service/team/index.js +1 -0
- package/dist/cjs/src/service/team/injury-replacement.d.ts +6 -0
- package/dist/cjs/src/service/team/injury-replacement.js +2 -0
- package/dist/cjs/src/service/team/schemas/injury-replacement.z.test.d.ts +1 -0
- package/dist/cjs/src/service/team/schemas/injury-replacement.z.test.js +142 -0
- package/dist/cjs/src/service/team/schemas/tactics.z.d.ts +6 -0
- package/dist/cjs/src/service/team/schemas/tactics.z.js +47 -1
- package/dist/cjs/src/service/team/schemas/team.z.d.ts +6 -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 +13 -1
- package/dist/esm/src/data/init-models.js +9 -1
- package/dist/esm/src/data/models/currency-transaction.d.ts +4 -2
- package/dist/esm/src/data/models/currency-transaction.js +2 -0
- package/dist/esm/src/data/models/index.d.ts +2 -0
- package/dist/esm/src/data/models/index.js +2 -0
- package/dist/esm/src/data/models/match-set.d.ts +2 -0
- package/dist/esm/src/data/models/match-set.js +5 -0
- package/dist/esm/src/data/models/match.d.ts +3 -1
- package/dist/esm/src/data/models/match.js +4 -0
- package/dist/esm/src/data/models/physician.d.ts +25 -0
- package/dist/esm/src/data/models/physician.js +53 -0
- package/dist/esm/src/data/models/physiotherapist.d.ts +25 -0
- package/dist/esm/src/data/models/physiotherapist.js +53 -0
- package/dist/esm/src/data/models/player.d.ts +8 -0
- package/dist/esm/src/data/models/player.js +17 -0
- package/dist/esm/src/data/models/tactics.d.ts +10 -1
- package/dist/esm/src/data/models/tactics.js +9 -0
- package/dist/esm/src/data/transformers/lineup-preset.js +7 -1
- package/dist/esm/src/data/transformers/lineup-preset.test.js +15 -2
- package/dist/esm/src/data/transformers/match-set.js +2 -0
- package/dist/esm/src/data/transformers/match.js +6 -2
- package/dist/esm/src/data/transformers/player.js +15 -1
- package/dist/esm/src/data/transformers/rally-event-injury.test.d.ts +1 -0
- package/dist/esm/src/data/transformers/rally-event-injury.test.js +31 -0
- package/dist/esm/src/data/transformers/rally-event.d.ts +1 -0
- package/dist/esm/src/data/transformers/rally-event.js +4 -1
- package/dist/esm/src/data/transformers/tactics.js +83 -4
- package/dist/esm/src/service/event/schemas/substitution.z.d.ts +1 -0
- package/dist/esm/src/service/event/schemas/substitution.z.js +2 -1
- package/dist/esm/src/service/event/substitution.d.ts +1 -0
- package/dist/esm/src/service/event/substitution.js +4 -2
- package/dist/esm/src/service/match/match-set-forfeit.test.d.ts +1 -0
- package/dist/esm/src/service/match/match-set-forfeit.test.js +74 -0
- package/dist/esm/src/service/match/match-set.d.ts +8 -0
- package/dist/esm/src/service/match/match-set.js +23 -1
- package/dist/esm/src/service/match/match.d.ts +2 -0
- package/dist/esm/src/service/match/match.js +2 -1
- package/dist/esm/src/service/match/schemas/match-set.z.d.ts +1 -0
- package/dist/esm/src/service/match/schemas/match-set.z.js +30 -2
- package/dist/esm/src/service/match/schemas/match.z.d.ts +4 -0
- package/dist/esm/src/service/match/schemas/match.z.js +4 -1
- package/dist/esm/src/service/player/index.d.ts +1 -0
- package/dist/esm/src/service/player/index.js +1 -0
- package/dist/esm/src/service/player/injury.d.ts +14 -0
- package/dist/esm/src/service/player/injury.js +33 -0
- package/dist/esm/src/service/player/injury.test.d.ts +1 -0
- package/dist/esm/src/service/player/injury.test.js +76 -0
- package/dist/esm/src/service/player/player-generator.js +3 -1
- package/dist/esm/src/service/player/player.d.ts +3 -0
- package/dist/esm/src/service/player/player.js +3 -1
- package/dist/esm/src/service/player/schemas/player.z.d.ts +6 -0
- package/dist/esm/src/service/player/schemas/player.z.js +7 -0
- package/dist/esm/src/service/team/index.d.ts +1 -0
- package/dist/esm/src/service/team/index.js +1 -0
- package/dist/esm/src/service/team/injury-replacement.d.ts +6 -0
- package/dist/esm/src/service/team/injury-replacement.js +1 -0
- package/dist/esm/src/service/team/schemas/injury-replacement.z.test.d.ts +1 -0
- package/dist/esm/src/service/team/schemas/injury-replacement.z.test.js +140 -0
- package/dist/esm/src/service/team/schemas/tactics.z.d.ts +6 -0
- package/dist/esm/src/service/team/schemas/tactics.z.js +47 -1
- package/dist/esm/src/service/team/schemas/team.z.d.ts +6 -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
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { DataTypes, Model } from 'sequelize';
|
|
2
|
+
export class PhysiotherapistModel extends Model {
|
|
3
|
+
static initModel(sequelize) {
|
|
4
|
+
return PhysiotherapistModel.init({
|
|
5
|
+
physiotherapist_id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
allowNull: false,
|
|
8
|
+
primaryKey: true
|
|
9
|
+
},
|
|
10
|
+
team_id: {
|
|
11
|
+
type: DataTypes.UUID,
|
|
12
|
+
allowNull: false,
|
|
13
|
+
unique: true,
|
|
14
|
+
references: {
|
|
15
|
+
model: 'Team',
|
|
16
|
+
key: 'team_id'
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
name: {
|
|
20
|
+
type: DataTypes.STRING,
|
|
21
|
+
allowNull: false,
|
|
22
|
+
defaultValue: ''
|
|
23
|
+
},
|
|
24
|
+
rarity: {
|
|
25
|
+
type: DataTypes.STRING,
|
|
26
|
+
allowNull: false,
|
|
27
|
+
defaultValue: 'COMMON'
|
|
28
|
+
},
|
|
29
|
+
currency_invested: {
|
|
30
|
+
type: DataTypes.INTEGER,
|
|
31
|
+
allowNull: false,
|
|
32
|
+
defaultValue: 0
|
|
33
|
+
}
|
|
34
|
+
}, {
|
|
35
|
+
sequelize,
|
|
36
|
+
tableName: 'Physiotherapist',
|
|
37
|
+
schema: 'public',
|
|
38
|
+
timestamps: false,
|
|
39
|
+
indexes: [
|
|
40
|
+
{
|
|
41
|
+
name: 'Physiotherapist_pk',
|
|
42
|
+
unique: true,
|
|
43
|
+
fields: [{ name: 'physiotherapist_id' }]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'Physiotherapist_team_id_unique',
|
|
47
|
+
unique: true,
|
|
48
|
+
fields: [{ name: 'team_id' }]
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -15,6 +15,10 @@ export interface PlayerAttributes {
|
|
|
15
15
|
birth_iteration: number;
|
|
16
16
|
last_declined_iteration: number | null;
|
|
17
17
|
decline_profile: DeclineProfile;
|
|
18
|
+
injury_prone_profile?: number | string;
|
|
19
|
+
injury_severity?: number | null;
|
|
20
|
+
injured_until?: Date | string | null;
|
|
21
|
+
injury_debuff?: number | string | null;
|
|
18
22
|
PerformanceStat?: PerformanceStatsAttributes;
|
|
19
23
|
BoxScores?: BoxScoreAttributes[];
|
|
20
24
|
}
|
|
@@ -34,6 +38,10 @@ export declare class PlayerModel extends Model<PlayerAttributes, PlayerCreationA
|
|
|
34
38
|
birth_iteration: number;
|
|
35
39
|
last_declined_iteration: number | null;
|
|
36
40
|
decline_profile: DeclineProfile;
|
|
41
|
+
injury_prone_profile: number | string;
|
|
42
|
+
injury_severity: number | null;
|
|
43
|
+
injured_until: Date | string | null;
|
|
44
|
+
injury_debuff: number | string | null;
|
|
37
45
|
country: CountryModel;
|
|
38
46
|
getCountry: Sequelize.BelongsToGetAssociationMixin<CountryModel>;
|
|
39
47
|
setCountry: Sequelize.BelongsToSetAssociationMixin<CountryModel, CountryId>;
|
|
@@ -59,6 +59,23 @@ export class PlayerModel extends Model {
|
|
|
59
59
|
type: DataTypes.ENUM(...Object.values(DeclineProfileEnum)),
|
|
60
60
|
allowNull: false,
|
|
61
61
|
defaultValue: DeclineProfileEnum.STANDARD
|
|
62
|
+
},
|
|
63
|
+
injury_prone_profile: {
|
|
64
|
+
type: DataTypes.DECIMAL(3, 2),
|
|
65
|
+
allowNull: false,
|
|
66
|
+
defaultValue: 0.5
|
|
67
|
+
},
|
|
68
|
+
injury_severity: {
|
|
69
|
+
type: DataTypes.INTEGER,
|
|
70
|
+
allowNull: true
|
|
71
|
+
},
|
|
72
|
+
injured_until: {
|
|
73
|
+
type: DataTypes.DATE,
|
|
74
|
+
allowNull: true
|
|
75
|
+
},
|
|
76
|
+
injury_debuff: {
|
|
77
|
+
type: DataTypes.DECIMAL(3, 2),
|
|
78
|
+
allowNull: true
|
|
62
79
|
}
|
|
63
80
|
}, {
|
|
64
81
|
sequelize,
|
|
@@ -39,6 +39,11 @@ export interface SystemSetAttributes {
|
|
|
39
39
|
rotationSystem: RotationSystemEnum;
|
|
40
40
|
designatedSetters: PlayerId[];
|
|
41
41
|
}
|
|
42
|
+
export interface InjuryReplacementAttributes {
|
|
43
|
+
starterId: PlayerId;
|
|
44
|
+
replacementId: PlayerId;
|
|
45
|
+
benchBackfillId?: PlayerId;
|
|
46
|
+
}
|
|
42
47
|
export interface LiberoSetSubConfigAttributes {
|
|
43
48
|
mode: LiberoSubMode;
|
|
44
49
|
fatigueBand?: EnergyBand;
|
|
@@ -61,10 +66,12 @@ export interface TacticsAttributes {
|
|
|
61
66
|
offensive_preferences: OffensivePreferenceAttributes[];
|
|
62
67
|
system_sets?: SystemSetAttributes[];
|
|
63
68
|
offensive_preference_sets?: OffensivePreferenceAttributes[][];
|
|
69
|
+
replace_injured_immediately?: boolean;
|
|
70
|
+
injury_replacements?: InjuryReplacementAttributes[];
|
|
64
71
|
}
|
|
65
72
|
export type TacticsPk = 'team_id';
|
|
66
73
|
export type TacticsId = TacticsModel[TacticsPk];
|
|
67
|
-
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';
|
|
74
|
+
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_injured_immediately' | 'injury_replacements';
|
|
68
75
|
export type TacticsCreationAttributes = Optional<TacticsAttributes, TacticsOptionalAttributes>;
|
|
69
76
|
export declare class TacticsModel extends Model<TacticsAttributes, TacticsCreationAttributes> implements TacticsAttributes {
|
|
70
77
|
team_id: string;
|
|
@@ -81,6 +88,8 @@ export declare class TacticsModel extends Model<TacticsAttributes, TacticsCreati
|
|
|
81
88
|
offensive_preferences: OffensivePreferenceAttributes[];
|
|
82
89
|
system_sets?: SystemSetAttributes[];
|
|
83
90
|
offensive_preference_sets?: OffensivePreferenceAttributes[][];
|
|
91
|
+
replace_injured_immediately?: boolean;
|
|
92
|
+
injury_replacements?: InjuryReplacementAttributes[];
|
|
84
93
|
team: TeamModel;
|
|
85
94
|
getTeam: Sequelize.BelongsToGetAssociationMixin<TeamModel>;
|
|
86
95
|
setTeam: Sequelize.BelongsToSetAssociationMixin<TeamModel, TeamId>;
|
|
@@ -71,6 +71,15 @@ export class TacticsModel extends Model {
|
|
|
71
71
|
offensive_preference_sets: {
|
|
72
72
|
type: DataTypes.JSONB,
|
|
73
73
|
allowNull: true
|
|
74
|
+
},
|
|
75
|
+
replace_injured_immediately: {
|
|
76
|
+
type: DataTypes.BOOLEAN,
|
|
77
|
+
allowNull: false,
|
|
78
|
+
defaultValue: true
|
|
79
|
+
},
|
|
80
|
+
injury_replacements: {
|
|
81
|
+
type: DataTypes.JSONB,
|
|
82
|
+
allowNull: true
|
|
74
83
|
}
|
|
75
84
|
}, {
|
|
76
85
|
sequelize,
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
// `config` is already stored as the API Tactics DTO, so a preset row maps to its API shape with no hydration.
|
|
2
|
+
// Presets saved before the injuries fields exist lack replaceInjuredImmediately: heal it to the effective
|
|
3
|
+
// default (true, matching transformToTactics' hydration) so the DTO's required field is honest and a UI
|
|
4
|
+
// toggle seeded from an old preset cannot silently flip the user's effective setting on re-save.
|
|
2
5
|
function transformToObject(model) {
|
|
3
6
|
return {
|
|
4
7
|
presetId: model.preset_id,
|
|
5
8
|
name: model.name,
|
|
6
9
|
isActive: model.is_active,
|
|
7
10
|
orderIndex: model.order_index,
|
|
8
|
-
config:
|
|
11
|
+
config: {
|
|
12
|
+
...model.config,
|
|
13
|
+
replaceInjuredImmediately: model.config.replaceInjuredImmediately ?? true
|
|
14
|
+
}
|
|
9
15
|
};
|
|
10
16
|
}
|
|
11
17
|
export { transformToObject as transformToLineupPreset };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect } from '@jest/globals';
|
|
2
2
|
import { transformToLineupPreset } from './lineup-preset';
|
|
3
3
|
describe('transformToLineupPreset()', () => {
|
|
4
|
-
it('maps preset columns to the API shape and
|
|
4
|
+
it('maps preset columns to the API shape and heals a pre-injuries config to the effective default', () => {
|
|
5
5
|
const config = { lineup: { bench: [] }, substitutionBand: 'TIRED' };
|
|
6
6
|
const preset = transformToLineupPreset({
|
|
7
7
|
preset_id: 'p1',
|
|
@@ -16,8 +16,21 @@ describe('transformToLineupPreset()', () => {
|
|
|
16
16
|
name: 'Starters',
|
|
17
17
|
isActive: true,
|
|
18
18
|
orderIndex: 2,
|
|
19
|
+
// A config stored before the injuries fields lacks replaceInjuredImmediately; the transform heals it
|
|
20
|
+
// to true (the effective hydration default) so the DTO's required field is honest.
|
|
21
|
+
config: { ...config, replaceInjuredImmediately: true }
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it('keeps an explicit replaceInjuredImmediately: false', () => {
|
|
25
|
+
const config = { lineup: { bench: [] }, substitutionBand: 'TIRED', replaceInjuredImmediately: false };
|
|
26
|
+
const preset = transformToLineupPreset({
|
|
27
|
+
preset_id: 'p2',
|
|
28
|
+
team_id: 't1',
|
|
29
|
+
name: 'Risky',
|
|
30
|
+
is_active: false,
|
|
31
|
+
order_index: 3,
|
|
19
32
|
config
|
|
20
33
|
});
|
|
21
|
-
expect(preset.config).toBe(
|
|
34
|
+
expect(preset.config.replaceInjuredImmediately).toBe(false);
|
|
22
35
|
});
|
|
23
36
|
});
|
|
@@ -23,6 +23,7 @@ function transformToAttributes(set, matchId) {
|
|
|
23
23
|
is_tie_break: set.isTieBreak,
|
|
24
24
|
home_score: set.homeScore,
|
|
25
25
|
away_score: set.awayScore,
|
|
26
|
+
forfeited: set.forfeited,
|
|
26
27
|
player_positions: [...homeSetPositions, ...awaySetPositions],
|
|
27
28
|
BoxScores: (set.boxScores ?? []).map(transformFromBoxScore),
|
|
28
29
|
Rallies: (set.rallies ?? []).map((rally) => transformFromRally(rally, set.id))
|
|
@@ -39,6 +40,7 @@ function transformToObject(model) {
|
|
|
39
40
|
homeScore: model.home_score,
|
|
40
41
|
awayScore: model.away_score,
|
|
41
42
|
isTieBreak: model.is_tie_break,
|
|
43
|
+
forfeited: model.forfeited ?? false,
|
|
42
44
|
boxScores: (model.BoxScores ?? []).map(transformToBoxScore),
|
|
43
45
|
homePlayerPosition,
|
|
44
46
|
awayPlayerPosition,
|
|
@@ -8,7 +8,10 @@ function transformToAttributes(match) {
|
|
|
8
8
|
away_team: match.awayTeam.id,
|
|
9
9
|
home_team: match.homeTeam.id,
|
|
10
10
|
scheduled_date: match.scheduledDate,
|
|
11
|
-
status: match.status
|
|
11
|
+
status: match.status,
|
|
12
|
+
// Both directions on purpose (the read is in transformToObject below). NOTE for the Sim: updateMatch's
|
|
13
|
+
// completion write uses an explicit column list and must include forfeit_type or the marker is lost.
|
|
14
|
+
forfeit_type: match.forfeitType ?? null
|
|
12
15
|
};
|
|
13
16
|
}
|
|
14
17
|
function transformToObject(model, currentIteration, onPresetFallback) {
|
|
@@ -63,7 +66,8 @@ function transformToObject(model, currentIteration, onPresetFallback) {
|
|
|
63
66
|
VPERs,
|
|
64
67
|
homeScore,
|
|
65
68
|
awayScore,
|
|
66
|
-
winner: model.MatchResult?.Winner != null ? transformToTeam(model.MatchResult.Winner, currentIteration) : undefined
|
|
69
|
+
winner: model.MatchResult?.Winner != null ? transformToTeam(model.MatchResult.Winner, currentIteration) : undefined,
|
|
70
|
+
forfeitType: model.forfeit_type ?? undefined
|
|
67
71
|
});
|
|
68
72
|
}
|
|
69
73
|
export { transformToObject as transformToMatch, transformToAttributes as transformFromMatch };
|
|
@@ -21,7 +21,11 @@ function transformToAttributes(player) {
|
|
|
21
21
|
birth_age: player.birthAge,
|
|
22
22
|
birth_iteration: player.birthIteration,
|
|
23
23
|
last_declined_iteration: null,
|
|
24
|
-
decline_profile: player.declineProfile
|
|
24
|
+
decline_profile: player.declineProfile,
|
|
25
|
+
injury_prone_profile: player.injuryProneProfile,
|
|
26
|
+
injury_severity: player.injury?.severity ?? null,
|
|
27
|
+
injured_until: player.injury?.injuredUntil ?? null,
|
|
28
|
+
injury_debuff: player.injury?.debuff ?? null
|
|
25
29
|
};
|
|
26
30
|
}
|
|
27
31
|
function transformToBoxScoreTotals(model) {
|
|
@@ -87,6 +91,16 @@ function transformToObject(model, currentIteration) {
|
|
|
87
91
|
birthAge: model.birth_age,
|
|
88
92
|
birthIteration: model.birth_iteration,
|
|
89
93
|
declineProfile: model.decline_profile,
|
|
94
|
+
// DECIMAL comes back as a string from pg; schema-defaulted when the column is absent (pre-migration rows).
|
|
95
|
+
injuryProneProfile: model.injury_prone_profile != null ? Number(model.injury_prone_profile) : undefined,
|
|
96
|
+
// Severity defends against a partial write: an injured_until without severity reads as MINOR.
|
|
97
|
+
injury: model.injured_until != null
|
|
98
|
+
? {
|
|
99
|
+
severity: model.injury_severity != null ? Number(model.injury_severity) : 1,
|
|
100
|
+
injuredUntil: model.injured_until,
|
|
101
|
+
debuff: model.injury_debuff != null ? Number(model.injury_debuff) : undefined
|
|
102
|
+
}
|
|
103
|
+
: undefined,
|
|
90
104
|
boxScores: (model.BoxScores ?? []).map(transformToBoxScore),
|
|
91
105
|
boxScoreTotals
|
|
92
106
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it, expect } from '@jest/globals';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { EventTypeEnum, Substitution } from '../../service';
|
|
4
|
+
import { transformToCompact, transformToSubstitution } from './rally-event';
|
|
5
|
+
describe('rally-event compact round trip — injury substitution marker', () => {
|
|
6
|
+
const playerIn = uuidv4();
|
|
7
|
+
const playerOut = uuidv4();
|
|
8
|
+
const roster = [playerIn, playerOut];
|
|
9
|
+
const playerIndex = new Map(roster.map((id, i) => [id, i]));
|
|
10
|
+
it('packs the injury flag as j=1 and round-trips it', () => {
|
|
11
|
+
const sub = Substitution.create({ playerId: playerIn, playerOut, injury: true });
|
|
12
|
+
const compact = transformToCompact(sub, playerIndex);
|
|
13
|
+
expect(compact.j).toBe(1);
|
|
14
|
+
const decoded = transformToSubstitution(compact, roster);
|
|
15
|
+
expect(decoded.injury).toBe(true);
|
|
16
|
+
expect(decoded.playerId).toBe(playerIn);
|
|
17
|
+
expect(decoded.playerOut).toBe(playerOut);
|
|
18
|
+
});
|
|
19
|
+
it('omits j entirely for a normal substitution', () => {
|
|
20
|
+
const sub = Substitution.create({ playerId: playerIn, playerOut });
|
|
21
|
+
const compact = transformToCompact(sub, playerIndex);
|
|
22
|
+
expect('j' in compact).toBe(false);
|
|
23
|
+
const decoded = transformToSubstitution(compact, roster);
|
|
24
|
+
expect(decoded.injury).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
it('decodes a legacy compact event (no j key) as a non-injury substitution', () => {
|
|
27
|
+
const legacy = { p: 0, e: EventTypeEnum.SUBSTITUTION, o: 1 };
|
|
28
|
+
const decoded = transformToSubstitution(legacy, roster);
|
|
29
|
+
expect(decoded.injury).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -9,6 +9,7 @@ export interface CompactEvent {
|
|
|
9
9
|
b?: number[];
|
|
10
10
|
l?: number;
|
|
11
11
|
o?: number;
|
|
12
|
+
j?: number;
|
|
12
13
|
}
|
|
13
14
|
export declare function transformToCompact(evt: RallyEvent, playerIndex: Map<string, number>): CompactEvent;
|
|
14
15
|
export declare function transformToBlock(event: CompactEvent, roster: string[]): Block;
|
|
@@ -19,6 +19,8 @@ export function transformToCompact(evt, playerIndex) {
|
|
|
19
19
|
}
|
|
20
20
|
else if (evt instanceof Substitution) {
|
|
21
21
|
out.o = playerIndex.get(evt.playerOut);
|
|
22
|
+
if (evt.injury === true)
|
|
23
|
+
out.j = 1;
|
|
22
24
|
}
|
|
23
25
|
return out;
|
|
24
26
|
}
|
|
@@ -78,6 +80,7 @@ export function transformToSpike(event, roster) {
|
|
|
78
80
|
export function transformToSubstitution(event, roster) {
|
|
79
81
|
return Substitution.create({
|
|
80
82
|
playerId: roster[event.p],
|
|
81
|
-
playerOut: roster[event.o]
|
|
83
|
+
playerOut: roster[event.o],
|
|
84
|
+
injury: event.j === 1 ? true : undefined
|
|
82
85
|
});
|
|
83
86
|
}
|
|
@@ -81,7 +81,13 @@ function transformToAttributes(tactics, teamId) {
|
|
|
81
81
|
offensive_preference_sets: tactics.offensivePreferenceSets?.map(prefs => prefs.map(p => ({
|
|
82
82
|
rotation: p.rotation,
|
|
83
83
|
order: p.order.map((a) => a.id)
|
|
84
|
-
})))
|
|
84
|
+
}))),
|
|
85
|
+
replace_injured_immediately: tactics.replaceInjuredImmediately,
|
|
86
|
+
injury_replacements: tactics.injuryReplacements.map(ir => ({
|
|
87
|
+
starterId: ir.starter.id,
|
|
88
|
+
replacementId: ir.replacement.id,
|
|
89
|
+
benchBackfillId: ir.benchBackfill?.id
|
|
90
|
+
}))
|
|
85
91
|
};
|
|
86
92
|
}
|
|
87
93
|
// Accepts TacticsAttributes (not just TacticsModel) so a per-match preset's config, shaped as column data by
|
|
@@ -158,7 +164,46 @@ function transformToObject(model, roster) {
|
|
|
158
164
|
offensivePreferenceSets: model.offensive_preference_sets?.map(prefs => prefs.map(p => ({
|
|
159
165
|
rotation: p.rotation,
|
|
160
166
|
order: p.order.map((id) => findPlayer(id, roster))
|
|
161
|
-
})))
|
|
167
|
+
}))),
|
|
168
|
+
replaceInjuredImmediately: model.replace_injured_immediately ?? true,
|
|
169
|
+
// LENIENT (roster.find, not findPlayer): an entry whose starter or replacement is gone/invalid is DROPPED
|
|
170
|
+
// rather than crashing the sim batch (a dropped entry = unconfigured = the bench-only auto fallback, per
|
|
171
|
+
// the owner rules); an invalid benchBackfill drops only the backfill. First occurrence wins on duplicates;
|
|
172
|
+
// the next tactics save rewrites cleanly. Schema invariants mirrored: starter must be a court starter,
|
|
173
|
+
// replacement bench-or-reserve (never a starter/libero/L2), backfill only-with-bench-replacement + reserve.
|
|
174
|
+
injuryReplacements: (() => {
|
|
175
|
+
const starterIds = new Set([lineup[CourtPosition.LEFT_FRONT], lineup[CourtPosition.MIDDLE_FRONT], lineup[CourtPosition.RIGHT_FRONT],
|
|
176
|
+
lineup[CourtPosition.LEFT_BACK], lineup[CourtPosition.MIDDLE_BACK], lineup[CourtPosition.RIGHT_BACK]]
|
|
177
|
+
.map((p) => p.id));
|
|
178
|
+
const benchIds = new Set(lineup.bench.map((p) => p.id));
|
|
179
|
+
const seenStarters = new Set();
|
|
180
|
+
const seenIncoming = new Set();
|
|
181
|
+
const healed = [];
|
|
182
|
+
for (const ir of model.injury_replacements ?? []) {
|
|
183
|
+
const starter = roster.find((p) => p.id === ir.starterId);
|
|
184
|
+
const replacement = roster.find((p) => p.id === ir.replacementId);
|
|
185
|
+
if (starter == null || replacement == null)
|
|
186
|
+
continue;
|
|
187
|
+
if (!starterIds.has(starter.id) || seenStarters.has(starter.id))
|
|
188
|
+
continue;
|
|
189
|
+
if (starterIds.has(replacement.id) || replacement.id === lineup[CourtPosition.LIBERO_ZONE]?.id ||
|
|
190
|
+
replacement.id === secondLibero?.id || seenIncoming.has(replacement.id))
|
|
191
|
+
continue;
|
|
192
|
+
seenStarters.add(starter.id);
|
|
193
|
+
seenIncoming.add(replacement.id);
|
|
194
|
+
let benchBackfill;
|
|
195
|
+
if (ir.benchBackfillId != null && benchIds.has(replacement.id)) {
|
|
196
|
+
const candidate = roster.find((p) => p.id === ir.benchBackfillId);
|
|
197
|
+
if (candidate != null && !inLineupIds.has(candidate.id) && candidate.id !== secondLibero?.id &&
|
|
198
|
+
!seenIncoming.has(candidate.id)) {
|
|
199
|
+
benchBackfill = candidate;
|
|
200
|
+
seenIncoming.add(candidate.id);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
healed.push({ starter, replacement, benchBackfill });
|
|
204
|
+
}
|
|
205
|
+
return healed;
|
|
206
|
+
})()
|
|
162
207
|
});
|
|
163
208
|
}
|
|
164
209
|
// Serialize a Tactics ROW (db columns) straight to the API Tactics DTO (player references stay as ids; no
|
|
@@ -218,7 +263,39 @@ function tacticsColumnsToApiDto(model) {
|
|
|
218
263
|
designatedSetters: model.designated_setters,
|
|
219
264
|
offensivePreferences: model.offensive_preferences,
|
|
220
265
|
systemSets: model.system_sets,
|
|
221
|
-
offensivePreferenceSets: model.offensive_preference_sets
|
|
266
|
+
offensivePreferenceSets: model.offensive_preference_sets,
|
|
267
|
+
replaceInjuredImmediately: model.replace_injured_immediately ?? true,
|
|
268
|
+
// Same stale-data policy as validSecondLibero above: don't surface entries the service load would drop
|
|
269
|
+
// (starter no longer a starter, replacement now a starter/libero/L2, duplicates), or the UI reloads and
|
|
270
|
+
// re-emits them forever. Roster membership can't be checked here (ids only); the service heal covers that.
|
|
271
|
+
injuryReplacements: (() => {
|
|
272
|
+
const starterSlotIds = new Set([model.lineup[CourtPosition.LEFT_FRONT], model.lineup[CourtPosition.MIDDLE_FRONT],
|
|
273
|
+
model.lineup[CourtPosition.RIGHT_FRONT], model.lineup[CourtPosition.LEFT_BACK],
|
|
274
|
+
model.lineup[CourtPosition.MIDDLE_BACK], model.lineup[CourtPosition.RIGHT_BACK]]);
|
|
275
|
+
const benchIdSet = new Set(model.lineup.bench);
|
|
276
|
+
const liberoId = model.lineup[CourtPosition.LIBERO_ZONE];
|
|
277
|
+
const seenStarters = new Set();
|
|
278
|
+
const seenIncoming = new Set();
|
|
279
|
+
const healed = [];
|
|
280
|
+
for (const ir of model.injury_replacements ?? []) {
|
|
281
|
+
if (!starterSlotIds.has(ir.starterId) || seenStarters.has(ir.starterId))
|
|
282
|
+
continue;
|
|
283
|
+
if (starterSlotIds.has(ir.replacementId) || ir.replacementId === liberoId ||
|
|
284
|
+
ir.replacementId === validSecondLibero || seenIncoming.has(ir.replacementId))
|
|
285
|
+
continue;
|
|
286
|
+
seenStarters.add(ir.starterId);
|
|
287
|
+
seenIncoming.add(ir.replacementId);
|
|
288
|
+
let benchBackfillId;
|
|
289
|
+
if (ir.benchBackfillId != null && benchIdSet.has(ir.replacementId) &&
|
|
290
|
+
!lineupIds.has(ir.benchBackfillId) && ir.benchBackfillId !== validSecondLibero &&
|
|
291
|
+
!seenIncoming.has(ir.benchBackfillId)) {
|
|
292
|
+
benchBackfillId = ir.benchBackfillId;
|
|
293
|
+
seenIncoming.add(benchBackfillId);
|
|
294
|
+
}
|
|
295
|
+
healed.push({ starterId: ir.starterId, replacementId: ir.replacementId, benchBackfillId });
|
|
296
|
+
}
|
|
297
|
+
return healed.length > 0 ? healed : undefined;
|
|
298
|
+
})()
|
|
222
299
|
};
|
|
223
300
|
}
|
|
224
301
|
// Inverse of tacticsColumnsToApiDto: shape a preset's stored API config (camelCase, player ids) as
|
|
@@ -251,7 +328,9 @@ function apiTacticsConfigToAttributes(config, teamId) {
|
|
|
251
328
|
designated_setters: config.designatedSetters,
|
|
252
329
|
offensive_preferences: config.offensivePreferences,
|
|
253
330
|
system_sets: config.systemSets,
|
|
254
|
-
offensive_preference_sets: config.offensivePreferenceSets
|
|
331
|
+
offensive_preference_sets: config.offensivePreferenceSets,
|
|
332
|
+
replace_injured_immediately: config.replaceInjuredImmediately,
|
|
333
|
+
injury_replacements: config.injuryReplacements
|
|
255
334
|
};
|
|
256
335
|
}
|
|
257
336
|
export { transformToObject as transformToTactics, transformToAttributes as transformFromTactics, tacticsColumnsToApiDto, apiTacticsConfigToAttributes as apiTacticsConfigToTacticsAttributes };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export const SubstitutionInputSchema = z.object({
|
|
3
3
|
playerId: z.uuid(),
|
|
4
|
-
playerOut: z.uuid()
|
|
4
|
+
playerOut: z.uuid(),
|
|
5
|
+
injury: z.boolean().optional()
|
|
5
6
|
}).superRefine((data, ctx) => {
|
|
6
7
|
if (data.playerId === data.playerOut) {
|
|
7
8
|
ctx.addIssue({
|
|
@@ -14,14 +14,16 @@ export class Substitution extends RallyEvent {
|
|
|
14
14
|
}
|
|
15
15
|
return new Substitution(result.data);
|
|
16
16
|
}
|
|
17
|
-
constructor({ playerOut, playerId }) {
|
|
17
|
+
constructor({ playerOut, playerId, injury }) {
|
|
18
18
|
super({ eventType, playerId });
|
|
19
19
|
this.playerOut = playerOut;
|
|
20
|
+
this.injury = injury;
|
|
20
21
|
}
|
|
21
22
|
toString() {
|
|
22
23
|
const playerId = `"playerId":"${this.playerId}"`;
|
|
23
24
|
const playerOut = `"playerOut":"${this.playerOut}"`;
|
|
24
25
|
const eventType = `"eventType":${this.eventType}`;
|
|
25
|
-
|
|
26
|
+
const injury = this.injury === true ? ',"injury":true' : '';
|
|
27
|
+
return `{${playerId},${playerOut},${eventType}${injury}}`;
|
|
26
28
|
}
|
|
27
29
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { describe, it, expect } from '@jest/globals';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { MatchSet } from './match-set';
|
|
4
|
+
import { MatchTeam } from './match-team';
|
|
5
|
+
function makeSet(homeScore, awayScore, isTieBreak = false, forfeited) {
|
|
6
|
+
return MatchSet.create({
|
|
7
|
+
id: uuidv4(),
|
|
8
|
+
order: isTieBreak ? 4 : 0,
|
|
9
|
+
isTieBreak,
|
|
10
|
+
homePlayerPosition: [],
|
|
11
|
+
awayPlayerPosition: [],
|
|
12
|
+
homeScore,
|
|
13
|
+
awayScore,
|
|
14
|
+
boxScores: [],
|
|
15
|
+
rallies: [],
|
|
16
|
+
...(forfeited != null ? { forfeited } : {})
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
// Mid-set states are not valid CREATION states (the schema wants 0-0 or a finished score), so build them the
|
|
20
|
+
// way the sim does: create at 0-0 and play to the score.
|
|
21
|
+
function playedTo(homeScore, awayScore, isTieBreak = false) {
|
|
22
|
+
const set = makeSet(0, 0, isTieBreak);
|
|
23
|
+
for (let i = 0; i < homeScore; i++)
|
|
24
|
+
set.increaseScore(MatchTeam.HOME);
|
|
25
|
+
for (let i = 0; i < awayScore; i++)
|
|
26
|
+
set.increaseScore(MatchTeam.AWAY);
|
|
27
|
+
return set;
|
|
28
|
+
}
|
|
29
|
+
describe('MatchSet — forfeit (FIVB 6.4.3)', () => {
|
|
30
|
+
it('defaults forfeited to false', () => {
|
|
31
|
+
expect(makeSet(25, 20).forfeited).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
it('accepts a persisted forfeited set with an awarded score', () => {
|
|
34
|
+
const set = makeSet(25, 13, false, true);
|
|
35
|
+
expect(set.forfeited).toBe(true);
|
|
36
|
+
expect(set.isOver()).toBe(true);
|
|
37
|
+
expect(set.getWinner()).toBe(MatchTeam.HOME);
|
|
38
|
+
});
|
|
39
|
+
it('awards the threshold when the loser is below deuce (18-23, home granted)', () => {
|
|
40
|
+
const set = playedTo(18, 23);
|
|
41
|
+
// Score order in makeSet is home, away; away leads 23-18 but HOME is granted the forfeit win.
|
|
42
|
+
set.forfeit(MatchTeam.HOME);
|
|
43
|
+
expect(set.homeScore).toBe(25);
|
|
44
|
+
expect(set.awayScore).toBe(23);
|
|
45
|
+
expect(set.forfeited).toBe(true);
|
|
46
|
+
expect(set.isOver()).toBe(true);
|
|
47
|
+
expect(set.getWinner()).toBe(MatchTeam.HOME);
|
|
48
|
+
});
|
|
49
|
+
it('awards loser + 2 beyond deuce (24-24, away granted -> 24-26)', () => {
|
|
50
|
+
const set = playedTo(24, 24);
|
|
51
|
+
set.forfeit(MatchTeam.AWAY);
|
|
52
|
+
expect(set.homeScore).toBe(24);
|
|
53
|
+
expect(set.awayScore).toBe(26);
|
|
54
|
+
expect(set.isOver()).toBe(true);
|
|
55
|
+
expect(set.getWinner()).toBe(MatchTeam.AWAY);
|
|
56
|
+
});
|
|
57
|
+
it('keeps the forfeiting side points (0-0 fully-awarded set -> 25-0)', () => {
|
|
58
|
+
const set = makeSet(0, 0);
|
|
59
|
+
set.forfeit(MatchTeam.HOME);
|
|
60
|
+
expect(set.homeScore).toBe(25);
|
|
61
|
+
expect(set.awayScore).toBe(0);
|
|
62
|
+
expect(set.isOver()).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
it('awards 15 on a tie break', () => {
|
|
65
|
+
const set = playedTo(10, 13, true);
|
|
66
|
+
set.forfeit(MatchTeam.HOME);
|
|
67
|
+
expect(set.homeScore).toBe(15);
|
|
68
|
+
expect(set.awayScore).toBe(13);
|
|
69
|
+
expect(set.isOver()).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('rejects a forfeited set whose score never reached the awarding rule (below threshold)', () => {
|
|
72
|
+
expect(() => makeSet(18, 12, false, true)).toThrow(/INVALID_MATCH_SET/);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -13,10 +13,18 @@ export declare class MatchSet {
|
|
|
13
13
|
readonly scoreThreshold: ScoreThreshold;
|
|
14
14
|
private _homeScore;
|
|
15
15
|
private _awayScore;
|
|
16
|
+
private _forfeited;
|
|
16
17
|
static create(input: unknown): MatchSet;
|
|
17
18
|
private constructor();
|
|
18
19
|
get homeScore(): number;
|
|
19
20
|
get awayScore(): number;
|
|
21
|
+
get forfeited(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* End the set by forfeit (FIVB 6.4.3, incomplete team). The forfeiting side keeps its points; the winner
|
|
24
|
+
* is granted exactly the points needed to win the set (the threshold, or loser + 2 beyond deuce), so the
|
|
25
|
+
* final score always satisfies the normal reached-threshold and win-by-2 rules. Marks the set forfeited.
|
|
26
|
+
*/
|
|
27
|
+
forfeit(winner: MatchTeam): void;
|
|
20
28
|
increaseScore(team: MatchTeam): void;
|
|
21
29
|
addRally(rally: Rally): void;
|
|
22
30
|
/**
|
|
@@ -13,11 +13,12 @@ export class MatchSet {
|
|
|
13
13
|
}
|
|
14
14
|
return new MatchSet(result.data);
|
|
15
15
|
}
|
|
16
|
-
constructor({ id, order, isTieBreak, homePlayerPosition, awayPlayerPosition, boxScores, rallies, homeScore, awayScore }) {
|
|
16
|
+
constructor({ id, order, isTieBreak, homePlayerPosition, awayPlayerPosition, boxScores, rallies, homeScore, awayScore, forfeited = false }) {
|
|
17
17
|
this.id = id;
|
|
18
18
|
this.order = order;
|
|
19
19
|
this._homeScore = homeScore;
|
|
20
20
|
this._awayScore = awayScore;
|
|
21
|
+
this._forfeited = forfeited;
|
|
21
22
|
this.homePlayerPosition = homePlayerPosition;
|
|
22
23
|
this.awayPlayerPosition = awayPlayerPosition;
|
|
23
24
|
this.boxScores = boxScores;
|
|
@@ -31,6 +32,27 @@ export class MatchSet {
|
|
|
31
32
|
get awayScore() {
|
|
32
33
|
return this._awayScore;
|
|
33
34
|
}
|
|
35
|
+
get forfeited() {
|
|
36
|
+
return this._forfeited;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* End the set by forfeit (FIVB 6.4.3, incomplete team). The forfeiting side keeps its points; the winner
|
|
40
|
+
* is granted exactly the points needed to win the set (the threshold, or loser + 2 beyond deuce), so the
|
|
41
|
+
* final score always satisfies the normal reached-threshold and win-by-2 rules. Marks the set forfeited.
|
|
42
|
+
*/
|
|
43
|
+
forfeit(winner) {
|
|
44
|
+
// Forfeiting an already-decided (or already-forfeited) set would silently rewrite the winner with a
|
|
45
|
+
// schema-legal score: surface the caller bug instead (e.g. both teams forfeited in the same rally).
|
|
46
|
+
if (this._forfeited || this.isOver())
|
|
47
|
+
throw new Error('SET_ALREADY_DECIDED');
|
|
48
|
+
if (winner === MatchTeam.HOME)
|
|
49
|
+
this._homeScore = Math.max(this.scoreThreshold, this._awayScore + 2);
|
|
50
|
+
else if (winner === MatchTeam.AWAY)
|
|
51
|
+
this._awayScore = Math.max(this.scoreThreshold, this._homeScore + 2);
|
|
52
|
+
else
|
|
53
|
+
throw new Error('UNKNOWN_TEAM');
|
|
54
|
+
this._forfeited = true;
|
|
55
|
+
}
|
|
34
56
|
increaseScore(team) {
|
|
35
57
|
if (team === MatchTeam.HOME)
|
|
36
58
|
this._homeScore++;
|
|
@@ -3,6 +3,7 @@ import { Team } from '../team';
|
|
|
3
3
|
import { MatchTeam } from './match-team';
|
|
4
4
|
import { StatusEnum } from '../../data';
|
|
5
5
|
import { VPER } from './vper';
|
|
6
|
+
export type MatchForfeitType = 'INCOMPLETE' | 'DEFAULT';
|
|
6
7
|
export type MatchScore = '3-0' | '3-1' | '3-2' | '2-3' | '1-3' | '0-3';
|
|
7
8
|
export type SetScore = 0 | 1 | 2 | 3;
|
|
8
9
|
export declare class Match {
|
|
@@ -16,6 +17,7 @@ export declare class Match {
|
|
|
16
17
|
homeScore?: number;
|
|
17
18
|
awayScore?: number;
|
|
18
19
|
winner?: Team;
|
|
20
|
+
forfeitType?: MatchForfeitType;
|
|
19
21
|
static create(input: unknown): Match;
|
|
20
22
|
private constructor();
|
|
21
23
|
addSet(set: MatchSet): void;
|