volleyballsimtypes 0.0.205 → 0.0.207
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/data/init-models.js +7 -1
- 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/match.d.ts +13 -1
- package/dist/cjs/src/data/models/player.d.ts +12 -1
- package/dist/cjs/src/data/models/views/match-result.d.ts +4 -4
- package/dist/cjs/src/data/models/views/match-result.js +4 -4
- package/dist/cjs/src/data/models/vper.d.ts +25 -0
- package/dist/cjs/src/data/models/vper.js +46 -0
- package/dist/cjs/src/data/transformers/index.d.ts +1 -0
- package/dist/cjs/src/data/transformers/index.js +1 -0
- package/dist/cjs/src/data/transformers/match.js +8 -2
- package/dist/cjs/src/data/transformers/team.js +3 -3
- package/dist/cjs/src/data/transformers/vper.d.ts +5 -0
- package/dist/cjs/src/data/transformers/vper.js +20 -0
- package/dist/cjs/src/service/match/index.d.ts +1 -0
- package/dist/cjs/src/service/match/index.js +1 -0
- package/dist/cjs/src/service/match/match.d.ts +4 -1
- package/dist/cjs/src/service/match/match.js +2 -1
- package/dist/cjs/src/service/match/vper.d.ts +13 -0
- package/dist/cjs/src/service/match/vper.js +56 -0
- package/dist/cjs/src/service/team/tactics.d.ts +1 -1
- package/dist/cjs/src/service/team/team.d.ts +2 -2
- package/dist/cjs/src/service/utils/object-utils.d.ts +3 -0
- package/dist/esm/src/data/init-models.js +8 -2
- 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/match.d.ts +13 -1
- package/dist/esm/src/data/models/player.d.ts +12 -1
- package/dist/esm/src/data/models/views/match-result.d.ts +4 -4
- package/dist/esm/src/data/models/views/match-result.js +4 -4
- package/dist/esm/src/data/models/vper.d.ts +25 -0
- package/dist/esm/src/data/models/vper.js +42 -0
- package/dist/esm/src/data/transformers/index.d.ts +1 -0
- package/dist/esm/src/data/transformers/index.js +1 -0
- package/dist/esm/src/data/transformers/match.js +8 -2
- package/dist/esm/src/data/transformers/team.js +3 -3
- package/dist/esm/src/data/transformers/vper.d.ts +5 -0
- package/dist/esm/src/data/transformers/vper.js +16 -0
- package/dist/esm/src/service/match/index.d.ts +1 -0
- package/dist/esm/src/service/match/index.js +1 -0
- package/dist/esm/src/service/match/match.d.ts +4 -1
- package/dist/esm/src/service/match/match.js +2 -1
- package/dist/esm/src/service/match/vper.d.ts +13 -0
- package/dist/esm/src/service/match/vper.js +52 -0
- package/dist/esm/src/service/team/tactics.d.ts +1 -1
- package/dist/esm/src/service/team/team.d.ts +2 -2
- package/dist/esm/src/service/utils/object-utils.d.ts +3 -0
- package/package.json +1 -1
|
@@ -28,6 +28,7 @@ function initModels(sequelize) {
|
|
|
28
28
|
const Rally = models_1.RallyModel.initModel(sequelize);
|
|
29
29
|
const Team = models_1.TeamModel.initModel(sequelize);
|
|
30
30
|
const User = models_1.UserModel.initModel(sequelize);
|
|
31
|
+
const VPER = models_1.VPERModel.initModel(sequelize);
|
|
31
32
|
Tactics.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
|
|
32
33
|
Competition.belongsTo(Iteration, { as: 'Iteration', foreignKey: 'iteration' });
|
|
33
34
|
Competition.hasMany(CompetitionMatch, { as: 'CompetitionMatches', foreignKey: 'competition_id' });
|
|
@@ -73,6 +74,7 @@ function initModels(sequelize) {
|
|
|
73
74
|
otherKey: 'team_id'
|
|
74
75
|
});
|
|
75
76
|
Match.hasMany(MatchRating, { as: 'MatchRatings', foreignKey: 'match_id' });
|
|
77
|
+
Match.hasMany(VPER, { as: 'VPERs', foreignKey: 'match_id' });
|
|
76
78
|
Match.hasMany(MatchSet, { as: 'MatchSets', foreignKey: 'match_id' });
|
|
77
79
|
Match.hasOne(CompetitionMatch, { as: 'CompetitionMatch', foreignKey: 'match_id' });
|
|
78
80
|
Match.hasOne(MatchResult, { as: 'MatchResult', foreignKey: 'match_id' });
|
|
@@ -107,6 +109,7 @@ function initModels(sequelize) {
|
|
|
107
109
|
otherKey: 'team_id'
|
|
108
110
|
});
|
|
109
111
|
Player.hasMany(BoxScore, { as: 'BoxScores', foreignKey: 'player_id' });
|
|
112
|
+
Player.hasMany(VPER, { as: 'VPERs', foreignKey: 'player_id' });
|
|
110
113
|
Player.hasMany(PlayerTeam, { as: 'PlayerTeams', foreignKey: 'player_id' });
|
|
111
114
|
Player.hasOne(DraftPick, { as: 'DraftPick', foreignKey: 'player_id' });
|
|
112
115
|
Player.hasOne(PerformanceStats, { as: 'PerformanceStat', foreignKey: 'player_id' });
|
|
@@ -114,6 +117,8 @@ function initModels(sequelize) {
|
|
|
114
117
|
PlayerTeam.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
|
|
115
118
|
Rally.belongsTo(MatchSet, { as: 'matchSet', foreignKey: 'match_set_id' });
|
|
116
119
|
Rally.belongsTo(Team, { as: 'ServingTeam', foreignKey: 'serving_team' });
|
|
120
|
+
VPER.belongsTo(Player, { as: 'Player', foreignKey: 'player_id' });
|
|
121
|
+
VPER.belongsTo(Match, { as: 'Match', foreignKey: 'match_id' });
|
|
117
122
|
Team.hasOne(Tactics, { as: 'tactics', foreignKey: 'team_id' });
|
|
118
123
|
Team.belongsTo(Country, { as: 'country', foreignKey: 'country_id' });
|
|
119
124
|
Team.belongsToMany(Competition, {
|
|
@@ -168,7 +173,8 @@ function initModels(sequelize) {
|
|
|
168
173
|
Rally,
|
|
169
174
|
Team,
|
|
170
175
|
Tactics,
|
|
171
|
-
User
|
|
176
|
+
User,
|
|
177
|
+
VPER
|
|
172
178
|
};
|
|
173
179
|
}
|
|
174
180
|
exports.initModels = initModels;
|
|
@@ -36,4 +36,5 @@ __exportStar(require("./rally"), exports);
|
|
|
36
36
|
__exportStar(require("./team"), exports);
|
|
37
37
|
__exportStar(require("./user"), exports);
|
|
38
38
|
__exportStar(require("./tactics"), exports);
|
|
39
|
+
__exportStar(require("./vper"), exports);
|
|
39
40
|
__exportStar(require("./views"), exports);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model } from 'sequelize';
|
|
3
3
|
import { Status } from '../common';
|
|
4
|
-
import { CompetitionMatchId, CompetitionMatchModel, MatchRatingId, MatchRatingModel, MatchResultId, MatchResultModel, MatchSetAttributes, MatchSetId, MatchSetModel, TeamId, TeamModel } from '.';
|
|
4
|
+
import { CompetitionMatchId, CompetitionMatchModel, MatchRatingId, MatchRatingModel, MatchResultId, MatchResultModel, MatchSetAttributes, MatchSetId, MatchSetModel, VPERAttributes, VPERId, VPERModel, TeamId, TeamModel } from '.';
|
|
5
5
|
export interface MatchAttributes {
|
|
6
6
|
match_id: string;
|
|
7
7
|
home_team: string;
|
|
@@ -9,6 +9,7 @@ export interface MatchAttributes {
|
|
|
9
9
|
scheduled_date: Date;
|
|
10
10
|
status: Status;
|
|
11
11
|
MatchSets?: MatchSetAttributes[];
|
|
12
|
+
VPERs?: VPERAttributes[];
|
|
12
13
|
}
|
|
13
14
|
export type MatchPk = 'match_id';
|
|
14
15
|
export type MatchId = MatchModel[MatchPk];
|
|
@@ -38,6 +39,17 @@ export declare class MatchModel extends Model<MatchAttributes, MatchCreationAttr
|
|
|
38
39
|
hasMatchRating: Sequelize.HasManyHasAssociationMixin<MatchRatingModel, MatchRatingId>;
|
|
39
40
|
hasMatchRatings: Sequelize.HasManyHasAssociationsMixin<MatchRatingModel, MatchRatingId>;
|
|
40
41
|
countMatchRatings: Sequelize.HasManyCountAssociationsMixin;
|
|
42
|
+
VPERs: VPERModel[];
|
|
43
|
+
getVPERs: Sequelize.HasManyGetAssociationsMixin<VPERModel>;
|
|
44
|
+
setVPERs: Sequelize.HasManySetAssociationsMixin<VPERModel, VPERId>;
|
|
45
|
+
addVPER: Sequelize.HasManyAddAssociationMixin<VPERModel, VPERId>;
|
|
46
|
+
addVPERs: Sequelize.HasManyAddAssociationsMixin<VPERModel, VPERId>;
|
|
47
|
+
createVPER: Sequelize.HasManyCreateAssociationMixin<VPERModel>;
|
|
48
|
+
removeVPER: Sequelize.HasManyRemoveAssociationMixin<VPERModel, VPERId>;
|
|
49
|
+
removeVPERs: Sequelize.HasManyRemoveAssociationsMixin<VPERModel, VPERId>;
|
|
50
|
+
hasVPER: Sequelize.HasManyHasAssociationMixin<VPERModel, VPERId>;
|
|
51
|
+
hasVPERs: Sequelize.HasManyHasAssociationsMixin<VPERModel, VPERId>;
|
|
52
|
+
countVPERs: Sequelize.HasManyCountAssociationsMixin;
|
|
41
53
|
MatchSets: MatchSetModel[];
|
|
42
54
|
getMatchSets: Sequelize.HasManyGetAssociationsMixin<MatchSetModel>;
|
|
43
55
|
setMatchSets: Sequelize.HasManySetAssociationsMixin<MatchSetModel, MatchSetId>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model } from 'sequelize';
|
|
3
|
-
import { BoxScoreAttributes, BoxScoreId, BoxScoreModel, CountryId, CountryModel, DraftPickId, DraftPickModel, MatchSetId, MatchSetModel, PerformanceStatsAttributes, PerformanceStatsId, PerformanceStatsModel, PlayerTeamId, PlayerTeamModel, TeamId, TeamModel } from '.';
|
|
3
|
+
import { BoxScoreAttributes, BoxScoreId, BoxScoreModel, CountryId, CountryModel, DraftPickId, DraftPickModel, MatchSetId, MatchSetModel, PerformanceStatsAttributes, PerformanceStatsId, PerformanceStatsModel, PlayerTeamId, PlayerTeamModel, TeamId, TeamModel, VPERId, VPERModel } from '.';
|
|
4
4
|
import { Rarity, Role, Trait } from '../../service';
|
|
5
5
|
export interface PlayerAttributes {
|
|
6
6
|
player_id: string;
|
|
@@ -58,6 +58,17 @@ export declare class PlayerModel extends Model<PlayerAttributes, PlayerCreationA
|
|
|
58
58
|
getPerformanceStat: Sequelize.HasOneGetAssociationMixin<PerformanceStatsModel>;
|
|
59
59
|
setPerformanceStat: Sequelize.HasOneSetAssociationMixin<PerformanceStatsModel, PerformanceStatsId>;
|
|
60
60
|
createPerformanceStat: Sequelize.HasOneCreateAssociationMixin<PerformanceStatsModel>;
|
|
61
|
+
VPERs: VPERModel[];
|
|
62
|
+
getVPERs: Sequelize.HasManyGetAssociationsMixin<VPERModel>;
|
|
63
|
+
setVPERs: Sequelize.HasManySetAssociationsMixin<VPERModel, VPERId>;
|
|
64
|
+
addVPER: Sequelize.HasManyAddAssociationMixin<VPERModel, VPERId>;
|
|
65
|
+
addVPERs: Sequelize.HasManyAddAssociationsMixin<VPERModel, VPERId>;
|
|
66
|
+
createVPER: Sequelize.HasManyCreateAssociationMixin<VPERModel>;
|
|
67
|
+
removeVPER: Sequelize.HasManyRemoveAssociationMixin<VPERModel, VPERId>;
|
|
68
|
+
removeVPERs: Sequelize.HasManyRemoveAssociationsMixin<VPERModel, VPERId>;
|
|
69
|
+
hasVPER: Sequelize.HasManyHasAssociationMixin<VPERModel, VPERId>;
|
|
70
|
+
hasVPERs: Sequelize.HasManyHasAssociationsMixin<VPERModel, VPERId>;
|
|
71
|
+
countVPERs: Sequelize.HasManyCountAssociationsMixin;
|
|
61
72
|
PlayerTeams: PlayerTeamModel[];
|
|
62
73
|
getPlayerTeams: Sequelize.HasManyGetAssociationsMixin<PlayerTeamModel>;
|
|
63
74
|
setPlayerTeams: Sequelize.HasManySetAssociationsMixin<PlayerTeamModel, PlayerTeamId>;
|
|
@@ -3,8 +3,8 @@ import { Model } from 'sequelize';
|
|
|
3
3
|
import { MatchId, MatchModel, TeamId, TeamModel } from '..';
|
|
4
4
|
export interface MatchResultAttributes {
|
|
5
5
|
match_id: string;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
home_scores: number[];
|
|
7
|
+
away_scores: number[];
|
|
8
8
|
winner_team_id: string | null;
|
|
9
9
|
}
|
|
10
10
|
export type MatchResultPk = 'match_id';
|
|
@@ -12,8 +12,8 @@ export type MatchResultId = MatchResultModel[MatchResultPk];
|
|
|
12
12
|
export type MatchResultCreationAttributes = MatchResultAttributes;
|
|
13
13
|
export declare class MatchResultModel extends Model<MatchResultAttributes, MatchResultCreationAttributes> implements MatchResultAttributes {
|
|
14
14
|
match_id: string;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
home_scores: number[];
|
|
16
|
+
away_scores: number[];
|
|
17
17
|
winner_team_id: string | null;
|
|
18
18
|
Match: MatchModel;
|
|
19
19
|
getMatch: Sequelize.BelongsToGetAssociationMixin<MatchModel>;
|
|
@@ -10,12 +10,12 @@ class MatchResultModel extends sequelize_1.Model {
|
|
|
10
10
|
allowNull: false,
|
|
11
11
|
primaryKey: true
|
|
12
12
|
},
|
|
13
|
-
|
|
14
|
-
type: sequelize_1.DataTypes.INTEGER,
|
|
13
|
+
home_scores: {
|
|
14
|
+
type: sequelize_1.DataTypes.ARRAY(sequelize_1.DataTypes.INTEGER),
|
|
15
15
|
allowNull: false
|
|
16
16
|
},
|
|
17
|
-
|
|
18
|
-
type: sequelize_1.DataTypes.INTEGER,
|
|
17
|
+
away_scores: {
|
|
18
|
+
type: sequelize_1.DataTypes.ARRAY(sequelize_1.DataTypes.INTEGER),
|
|
19
19
|
allowNull: false
|
|
20
20
|
},
|
|
21
21
|
winner_team_id: {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as Sequelize from 'sequelize';
|
|
2
|
+
import { Model } from 'sequelize';
|
|
3
|
+
import { MatchId, MatchModel, PlayerId, PlayerModel } from '.';
|
|
4
|
+
export interface VPERAttributes {
|
|
5
|
+
player_id: string;
|
|
6
|
+
match_id: string;
|
|
7
|
+
value: number;
|
|
8
|
+
}
|
|
9
|
+
export type VPERPk = 'player_id' | 'match_id';
|
|
10
|
+
export type VPERId = VPERModel[VPERPk];
|
|
11
|
+
export type VPERCreationAttributes = VPERAttributes;
|
|
12
|
+
export declare class VPERModel extends Model<VPERAttributes, VPERCreationAttributes> implements VPERAttributes {
|
|
13
|
+
player_id: string;
|
|
14
|
+
match_id: string;
|
|
15
|
+
value: number;
|
|
16
|
+
Player: PlayerModel;
|
|
17
|
+
getPlayer: Sequelize.BelongsToGetAssociationMixin<PlayerModel>;
|
|
18
|
+
setPlayer: Sequelize.BelongsToSetAssociationMixin<PlayerModel, PlayerId>;
|
|
19
|
+
createPlayer: Sequelize.BelongsToCreateAssociationMixin<PlayerModel>;
|
|
20
|
+
Match: MatchModel;
|
|
21
|
+
getMatch: Sequelize.BelongsToGetAssociationMixin<MatchModel>;
|
|
22
|
+
setMatch: Sequelize.BelongsToSetAssociationMixin<MatchModel, MatchId>;
|
|
23
|
+
createMatch: Sequelize.BelongsToCreateAssociationMixin<MatchModel>;
|
|
24
|
+
static initModel(sequelize: Sequelize.Sequelize): typeof VPERModel;
|
|
25
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VPERModel = void 0;
|
|
4
|
+
const sequelize_1 = require("sequelize");
|
|
5
|
+
class VPERModel extends sequelize_1.Model {
|
|
6
|
+
static initModel(sequelize) {
|
|
7
|
+
return VPERModel.init({
|
|
8
|
+
player_id: {
|
|
9
|
+
type: sequelize_1.DataTypes.UUID,
|
|
10
|
+
allowNull: false,
|
|
11
|
+
primaryKey: true,
|
|
12
|
+
references: {
|
|
13
|
+
model: 'Player',
|
|
14
|
+
key: 'player_id'
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
match_id: {
|
|
18
|
+
type: sequelize_1.DataTypes.UUID,
|
|
19
|
+
allowNull: false,
|
|
20
|
+
primaryKey: true,
|
|
21
|
+
references: {
|
|
22
|
+
model: 'Match',
|
|
23
|
+
key: 'match_id'
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
value: {
|
|
27
|
+
type: sequelize_1.DataTypes.REAL,
|
|
28
|
+
allowNull: false
|
|
29
|
+
}
|
|
30
|
+
}, {
|
|
31
|
+
sequelize,
|
|
32
|
+
tableName: 'VPER',
|
|
33
|
+
schema: 'public',
|
|
34
|
+
timestamps: false,
|
|
35
|
+
indexes: [{
|
|
36
|
+
name: 'VPER_pk',
|
|
37
|
+
unique: true,
|
|
38
|
+
fields: [
|
|
39
|
+
{ name: 'player_id' },
|
|
40
|
+
{ name: 'match_id' }
|
|
41
|
+
]
|
|
42
|
+
}]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.VPERModel = VPERModel;
|
|
@@ -4,6 +4,7 @@ exports.transformFromMatch = exports.transformToMatch = void 0;
|
|
|
4
4
|
const service_1 = require("../../service");
|
|
5
5
|
const match_set_1 = require("./match-set");
|
|
6
6
|
const team_1 = require("./team");
|
|
7
|
+
const vper_1 = require("./vper");
|
|
7
8
|
function transformToAttributes(match) {
|
|
8
9
|
return {
|
|
9
10
|
match_id: match.id,
|
|
@@ -17,6 +18,10 @@ exports.transformFromMatch = transformToAttributes;
|
|
|
17
18
|
function transformToObject(model) {
|
|
18
19
|
const sets = (model.MatchSets ?? []).map(match_set_1.transformToMatchSet)
|
|
19
20
|
.sort((s1, s2) => s1.order - s2.order);
|
|
21
|
+
const homeScores = model.MatchResult?.home_scores ?? [];
|
|
22
|
+
const awayScores = model.MatchResult?.away_scores ?? [];
|
|
23
|
+
const sumScores = (scores) => scores.reduce((total, score) => total + score, 0);
|
|
24
|
+
const VPERs = (model.VPERs ?? []).map(vper_1.transformToVPER);
|
|
20
25
|
return new service_1.Match({
|
|
21
26
|
id: model.match_id,
|
|
22
27
|
homeTeam: (0, team_1.transformToTeam)(model.HomeTeam),
|
|
@@ -24,8 +29,9 @@ function transformToObject(model) {
|
|
|
24
29
|
scheduledDate: new Date(model.scheduled_date),
|
|
25
30
|
sets,
|
|
26
31
|
status: model.status,
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
VPERs,
|
|
33
|
+
homeScore: homeScores.length > 0 ? sumScores(homeScores) : undefined,
|
|
34
|
+
awayScore: awayScores.length > 0 ? sumScores(awayScores) : undefined,
|
|
29
35
|
winner: model.MatchResult?.Winner != null ? (0, team_1.transformToTeam)(model.MatchResult.Winner) : undefined
|
|
30
36
|
});
|
|
31
37
|
}
|
|
@@ -9,7 +9,7 @@ function transformToAttributes(team) {
|
|
|
9
9
|
name: team.name,
|
|
10
10
|
short_name: team.shortName,
|
|
11
11
|
country_id: team.country?.id,
|
|
12
|
-
tactics: (0, _1.transformFromTactics)(team.tactics, team.id),
|
|
12
|
+
tactics: team.tactics != null ? (0, _1.transformFromTactics)(team.tactics, team.id) : undefined,
|
|
13
13
|
rating: team.rating,
|
|
14
14
|
division_id: team.divisionId
|
|
15
15
|
};
|
|
@@ -22,9 +22,9 @@ function transformToObject(model) {
|
|
|
22
22
|
name: model.name,
|
|
23
23
|
shortName: model.short_name,
|
|
24
24
|
country: (0, _1.transformToCountry)(model.country),
|
|
25
|
-
tactics: (0, _1.transformToTactics)(model.tactics, roster),
|
|
26
|
-
roster,
|
|
27
25
|
rating: model.rating,
|
|
26
|
+
tactics: roster != null && roster.length > 0 ? (0, _1.transformToTactics)(model.tactics, roster) : undefined,
|
|
27
|
+
roster,
|
|
28
28
|
divisionId: model.division_id
|
|
29
29
|
});
|
|
30
30
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { VPERAttributes, VPERModel } from '../models';
|
|
2
|
+
import { VPER } from '../../service';
|
|
3
|
+
declare function transformToAttributes(vper: VPER): VPERAttributes;
|
|
4
|
+
declare function transformToObject(model: VPERModel): VPER;
|
|
5
|
+
export { transformToObject as transformToVPER, transformToAttributes as transformFromVPER };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformFromVPER = exports.transformToVPER = void 0;
|
|
4
|
+
const service_1 = require("../../service");
|
|
5
|
+
function transformToAttributes(vper) {
|
|
6
|
+
return {
|
|
7
|
+
player_id: vper.playerId,
|
|
8
|
+
match_id: vper.matchId,
|
|
9
|
+
value: vper.value
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
exports.transformFromVPER = transformToAttributes;
|
|
13
|
+
function transformToObject(model) {
|
|
14
|
+
return new service_1.VPER({
|
|
15
|
+
playerId: model.player_id,
|
|
16
|
+
matchId: model.match_id,
|
|
17
|
+
value: model.value
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
exports.transformToVPER = transformToObject;
|
|
@@ -2,6 +2,7 @@ import { MatchSet } from './match-set';
|
|
|
2
2
|
import { Team } from '../team';
|
|
3
3
|
import { MatchTeam } from './match-team';
|
|
4
4
|
import { StatusEnum } from '../../data';
|
|
5
|
+
import { VPER } from './vper';
|
|
5
6
|
interface MatchParams {
|
|
6
7
|
readonly id: string;
|
|
7
8
|
readonly homeTeam: Team;
|
|
@@ -9,6 +10,7 @@ interface MatchParams {
|
|
|
9
10
|
readonly scheduledDate: Date;
|
|
10
11
|
readonly sets: MatchSet[];
|
|
11
12
|
readonly status: StatusEnum;
|
|
13
|
+
readonly VPERs: VPER[];
|
|
12
14
|
homeScore?: number;
|
|
13
15
|
awayScore?: number;
|
|
14
16
|
winner?: Team;
|
|
@@ -21,11 +23,12 @@ export declare class Match {
|
|
|
21
23
|
readonly awayTeam: Team;
|
|
22
24
|
readonly sets: MatchSet[];
|
|
23
25
|
readonly scheduledDate: Date;
|
|
26
|
+
readonly VPERs: VPER[];
|
|
24
27
|
homeScore?: number;
|
|
25
28
|
awayScore?: number;
|
|
26
29
|
winner?: Team;
|
|
27
30
|
status: StatusEnum;
|
|
28
|
-
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner }: MatchParams);
|
|
31
|
+
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner, VPERs }: MatchParams);
|
|
29
32
|
addSet(set: MatchSet): void;
|
|
30
33
|
getTeamSets(team: MatchTeam): SetScore;
|
|
31
34
|
getScore(): MatchScore;
|
|
@@ -5,7 +5,7 @@ const utils_1 = require("../utils");
|
|
|
5
5
|
const match_team_1 = require("./match-team");
|
|
6
6
|
const data_1 = require("../../data");
|
|
7
7
|
class Match {
|
|
8
|
-
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner }) {
|
|
8
|
+
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner, VPERs }) {
|
|
9
9
|
(0, utils_1.validateUUID)(id);
|
|
10
10
|
this.id = id;
|
|
11
11
|
this.homeTeam = homeTeam;
|
|
@@ -16,6 +16,7 @@ class Match {
|
|
|
16
16
|
this.homeScore = homeScore;
|
|
17
17
|
this.awayScore = awayScore;
|
|
18
18
|
this.winner = winner;
|
|
19
|
+
this.VPERs = VPERs;
|
|
19
20
|
}
|
|
20
21
|
addSet(set) {
|
|
21
22
|
if (this.sets.length >= 5)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BoxScore } from './box-score';
|
|
2
|
+
export interface VPERParams {
|
|
3
|
+
readonly playerId: string;
|
|
4
|
+
readonly matchId: string;
|
|
5
|
+
readonly value: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class VPER {
|
|
8
|
+
readonly playerId: string;
|
|
9
|
+
readonly matchId: string;
|
|
10
|
+
readonly value: number;
|
|
11
|
+
constructor({ playerId, matchId, value }: VPERParams);
|
|
12
|
+
static computeVPERForMatch(boxScores: BoxScore[]): number;
|
|
13
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VPER = void 0;
|
|
4
|
+
const WEIGHTS = {
|
|
5
|
+
// terminal positive
|
|
6
|
+
ATTACK_KILL: 1.0,
|
|
7
|
+
SERVE_ACE: 1.0,
|
|
8
|
+
BLOCK_SOLO: 1.0,
|
|
9
|
+
BLOCK_ASSIST: 0.5,
|
|
10
|
+
// creation / continuation
|
|
11
|
+
SETTING_ASSIST: 0.7,
|
|
12
|
+
BLOCK_TOUCH: 0.2,
|
|
13
|
+
DEFENSE_DIG: 0.25,
|
|
14
|
+
SETTING_PASS: 0.15,
|
|
15
|
+
// reception quality
|
|
16
|
+
RECEPTION_PERFECT: 0.35,
|
|
17
|
+
RECEPTION_POSITIVE: 0.15,
|
|
18
|
+
RECEPTION_OVERPASS: -0.6,
|
|
19
|
+
// terminal errors (always point against)
|
|
20
|
+
TERMINAL_ERROR: -1.0
|
|
21
|
+
};
|
|
22
|
+
class VPER {
|
|
23
|
+
constructor({ playerId, matchId, value }) {
|
|
24
|
+
this.matchId = matchId;
|
|
25
|
+
this.playerId = playerId;
|
|
26
|
+
this.value = value;
|
|
27
|
+
}
|
|
28
|
+
static computeVPERForMatch(boxScores) {
|
|
29
|
+
let rawSum = 0;
|
|
30
|
+
let pointsPlayedSum = 0;
|
|
31
|
+
for (const box of boxScores) {
|
|
32
|
+
const w = WEIGHTS;
|
|
33
|
+
const positive = w.ATTACK_KILL * box.attack.kills +
|
|
34
|
+
w.SERVE_ACE * box.serve.aces +
|
|
35
|
+
w.BLOCK_SOLO * box.block.solo +
|
|
36
|
+
w.BLOCK_ASSIST * box.block.assists +
|
|
37
|
+
w.SETTING_ASSIST * box.setting.assists +
|
|
38
|
+
w.BLOCK_TOUCH * box.block.touches +
|
|
39
|
+
w.DEFENSE_DIG * box.defense.digs +
|
|
40
|
+
w.SETTING_PASS * box.setting.pass +
|
|
41
|
+
w.RECEPTION_PERFECT * box.reception.perfect +
|
|
42
|
+
w.RECEPTION_POSITIVE * box.reception.positive;
|
|
43
|
+
const negative = w.RECEPTION_OVERPASS * box.reception.overpasses +
|
|
44
|
+
w.TERMINAL_ERROR * (box.attack.errors +
|
|
45
|
+
box.serve.errors +
|
|
46
|
+
box.reception.errors +
|
|
47
|
+
box.defense.errors +
|
|
48
|
+
box.block.errors +
|
|
49
|
+
box.setting.errors);
|
|
50
|
+
rawSum += positive + negative;
|
|
51
|
+
pointsPlayedSum += box.misc.pointsPlayed;
|
|
52
|
+
}
|
|
53
|
+
return 100 * rawSum / Math.max(1, pointsPlayedSum);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.VPER = VPER;
|
|
@@ -12,7 +12,7 @@ export interface StartingLineup {
|
|
|
12
12
|
}
|
|
13
13
|
export interface TacticsOpts {
|
|
14
14
|
readonly lineup: StartingLineup;
|
|
15
|
-
readonly substitutionTolerance
|
|
15
|
+
readonly substitutionTolerance: number;
|
|
16
16
|
readonly liberoReplacements: Player[];
|
|
17
17
|
readonly pinchServerSubs: Map<Player, Player>;
|
|
18
18
|
}
|
|
@@ -9,7 +9,7 @@ interface TeamParams {
|
|
|
9
9
|
readonly divisionId: string;
|
|
10
10
|
readonly roster: Player[];
|
|
11
11
|
readonly country: Country;
|
|
12
|
-
readonly tactics
|
|
12
|
+
readonly tactics?: Tactics;
|
|
13
13
|
}
|
|
14
14
|
export declare class Team {
|
|
15
15
|
readonly id: string;
|
|
@@ -17,7 +17,7 @@ export declare class Team {
|
|
|
17
17
|
readonly name: string;
|
|
18
18
|
readonly shortName: string;
|
|
19
19
|
readonly divisionId: string;
|
|
20
|
-
readonly tactics
|
|
20
|
+
readonly tactics?: Tactics;
|
|
21
21
|
readonly country: Country;
|
|
22
22
|
private _rating;
|
|
23
23
|
constructor({ id, rating, name, shortName, divisionId, country, roster, tactics }: TeamParams);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BoxScoreModel, BoxScoreTotalsModel, CompetitionChampionModel, CompetitionMatchModel, CompetitionModel, CompetitionTeamsModel, CountryModel, DivisionModel, DivisionSeasonModel, HistoricStandingsModel, DraftModel, DraftPickModel, IterationModel, LeagueModel, MatchModel, MatchRatingModel, MatchResultModel, MatchSetModel, PerformanceStatsModel, PlayerModel, PlayerTeamModel, RallyModel, TacticsModel, TeamModel, UserModel } from './models';
|
|
1
|
+
import { BoxScoreModel, BoxScoreTotalsModel, CompetitionChampionModel, CompetitionMatchModel, CompetitionModel, CompetitionTeamsModel, CountryModel, DivisionModel, DivisionSeasonModel, HistoricStandingsModel, DraftModel, DraftPickModel, IterationModel, LeagueModel, MatchModel, MatchRatingModel, MatchResultModel, MatchSetModel, PerformanceStatsModel, PlayerModel, PlayerTeamModel, RallyModel, TacticsModel, TeamModel, UserModel, VPERModel } from './models';
|
|
2
2
|
export function initModels(sequelize) {
|
|
3
3
|
const Tactics = TacticsModel.initModel(sequelize);
|
|
4
4
|
const Country = CountryModel.initModel(sequelize);
|
|
@@ -25,6 +25,7 @@ export function initModels(sequelize) {
|
|
|
25
25
|
const Rally = RallyModel.initModel(sequelize);
|
|
26
26
|
const Team = TeamModel.initModel(sequelize);
|
|
27
27
|
const User = UserModel.initModel(sequelize);
|
|
28
|
+
const VPER = VPERModel.initModel(sequelize);
|
|
28
29
|
Tactics.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
|
|
29
30
|
Competition.belongsTo(Iteration, { as: 'Iteration', foreignKey: 'iteration' });
|
|
30
31
|
Competition.hasMany(CompetitionMatch, { as: 'CompetitionMatches', foreignKey: 'competition_id' });
|
|
@@ -70,6 +71,7 @@ export function initModels(sequelize) {
|
|
|
70
71
|
otherKey: 'team_id'
|
|
71
72
|
});
|
|
72
73
|
Match.hasMany(MatchRating, { as: 'MatchRatings', foreignKey: 'match_id' });
|
|
74
|
+
Match.hasMany(VPER, { as: 'VPERs', foreignKey: 'match_id' });
|
|
73
75
|
Match.hasMany(MatchSet, { as: 'MatchSets', foreignKey: 'match_id' });
|
|
74
76
|
Match.hasOne(CompetitionMatch, { as: 'CompetitionMatch', foreignKey: 'match_id' });
|
|
75
77
|
Match.hasOne(MatchResult, { as: 'MatchResult', foreignKey: 'match_id' });
|
|
@@ -104,6 +106,7 @@ export function initModels(sequelize) {
|
|
|
104
106
|
otherKey: 'team_id'
|
|
105
107
|
});
|
|
106
108
|
Player.hasMany(BoxScore, { as: 'BoxScores', foreignKey: 'player_id' });
|
|
109
|
+
Player.hasMany(VPER, { as: 'VPERs', foreignKey: 'player_id' });
|
|
107
110
|
Player.hasMany(PlayerTeam, { as: 'PlayerTeams', foreignKey: 'player_id' });
|
|
108
111
|
Player.hasOne(DraftPick, { as: 'DraftPick', foreignKey: 'player_id' });
|
|
109
112
|
Player.hasOne(PerformanceStats, { as: 'PerformanceStat', foreignKey: 'player_id' });
|
|
@@ -111,6 +114,8 @@ export function initModels(sequelize) {
|
|
|
111
114
|
PlayerTeam.belongsTo(Team, { as: 'team', foreignKey: 'team_id' });
|
|
112
115
|
Rally.belongsTo(MatchSet, { as: 'matchSet', foreignKey: 'match_set_id' });
|
|
113
116
|
Rally.belongsTo(Team, { as: 'ServingTeam', foreignKey: 'serving_team' });
|
|
117
|
+
VPER.belongsTo(Player, { as: 'Player', foreignKey: 'player_id' });
|
|
118
|
+
VPER.belongsTo(Match, { as: 'Match', foreignKey: 'match_id' });
|
|
114
119
|
Team.hasOne(Tactics, { as: 'tactics', foreignKey: 'team_id' });
|
|
115
120
|
Team.belongsTo(Country, { as: 'country', foreignKey: 'country_id' });
|
|
116
121
|
Team.belongsToMany(Competition, {
|
|
@@ -165,6 +170,7 @@ export function initModels(sequelize) {
|
|
|
165
170
|
Rally,
|
|
166
171
|
Team,
|
|
167
172
|
Tactics,
|
|
168
|
-
User
|
|
173
|
+
User,
|
|
174
|
+
VPER
|
|
169
175
|
};
|
|
170
176
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model } from 'sequelize';
|
|
3
3
|
import { Status } from '../common';
|
|
4
|
-
import { CompetitionMatchId, CompetitionMatchModel, MatchRatingId, MatchRatingModel, MatchResultId, MatchResultModel, MatchSetAttributes, MatchSetId, MatchSetModel, TeamId, TeamModel } from '.';
|
|
4
|
+
import { CompetitionMatchId, CompetitionMatchModel, MatchRatingId, MatchRatingModel, MatchResultId, MatchResultModel, MatchSetAttributes, MatchSetId, MatchSetModel, VPERAttributes, VPERId, VPERModel, TeamId, TeamModel } from '.';
|
|
5
5
|
export interface MatchAttributes {
|
|
6
6
|
match_id: string;
|
|
7
7
|
home_team: string;
|
|
@@ -9,6 +9,7 @@ export interface MatchAttributes {
|
|
|
9
9
|
scheduled_date: Date;
|
|
10
10
|
status: Status;
|
|
11
11
|
MatchSets?: MatchSetAttributes[];
|
|
12
|
+
VPERs?: VPERAttributes[];
|
|
12
13
|
}
|
|
13
14
|
export type MatchPk = 'match_id';
|
|
14
15
|
export type MatchId = MatchModel[MatchPk];
|
|
@@ -38,6 +39,17 @@ export declare class MatchModel extends Model<MatchAttributes, MatchCreationAttr
|
|
|
38
39
|
hasMatchRating: Sequelize.HasManyHasAssociationMixin<MatchRatingModel, MatchRatingId>;
|
|
39
40
|
hasMatchRatings: Sequelize.HasManyHasAssociationsMixin<MatchRatingModel, MatchRatingId>;
|
|
40
41
|
countMatchRatings: Sequelize.HasManyCountAssociationsMixin;
|
|
42
|
+
VPERs: VPERModel[];
|
|
43
|
+
getVPERs: Sequelize.HasManyGetAssociationsMixin<VPERModel>;
|
|
44
|
+
setVPERs: Sequelize.HasManySetAssociationsMixin<VPERModel, VPERId>;
|
|
45
|
+
addVPER: Sequelize.HasManyAddAssociationMixin<VPERModel, VPERId>;
|
|
46
|
+
addVPERs: Sequelize.HasManyAddAssociationsMixin<VPERModel, VPERId>;
|
|
47
|
+
createVPER: Sequelize.HasManyCreateAssociationMixin<VPERModel>;
|
|
48
|
+
removeVPER: Sequelize.HasManyRemoveAssociationMixin<VPERModel, VPERId>;
|
|
49
|
+
removeVPERs: Sequelize.HasManyRemoveAssociationsMixin<VPERModel, VPERId>;
|
|
50
|
+
hasVPER: Sequelize.HasManyHasAssociationMixin<VPERModel, VPERId>;
|
|
51
|
+
hasVPERs: Sequelize.HasManyHasAssociationsMixin<VPERModel, VPERId>;
|
|
52
|
+
countVPERs: Sequelize.HasManyCountAssociationsMixin;
|
|
41
53
|
MatchSets: MatchSetModel[];
|
|
42
54
|
getMatchSets: Sequelize.HasManyGetAssociationsMixin<MatchSetModel>;
|
|
43
55
|
setMatchSets: Sequelize.HasManySetAssociationsMixin<MatchSetModel, MatchSetId>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as Sequelize from 'sequelize';
|
|
2
2
|
import { Model } from 'sequelize';
|
|
3
|
-
import { BoxScoreAttributes, BoxScoreId, BoxScoreModel, CountryId, CountryModel, DraftPickId, DraftPickModel, MatchSetId, MatchSetModel, PerformanceStatsAttributes, PerformanceStatsId, PerformanceStatsModel, PlayerTeamId, PlayerTeamModel, TeamId, TeamModel } from '.';
|
|
3
|
+
import { BoxScoreAttributes, BoxScoreId, BoxScoreModel, CountryId, CountryModel, DraftPickId, DraftPickModel, MatchSetId, MatchSetModel, PerformanceStatsAttributes, PerformanceStatsId, PerformanceStatsModel, PlayerTeamId, PlayerTeamModel, TeamId, TeamModel, VPERId, VPERModel } from '.';
|
|
4
4
|
import { Rarity, Role, Trait } from '../../service';
|
|
5
5
|
export interface PlayerAttributes {
|
|
6
6
|
player_id: string;
|
|
@@ -58,6 +58,17 @@ export declare class PlayerModel extends Model<PlayerAttributes, PlayerCreationA
|
|
|
58
58
|
getPerformanceStat: Sequelize.HasOneGetAssociationMixin<PerformanceStatsModel>;
|
|
59
59
|
setPerformanceStat: Sequelize.HasOneSetAssociationMixin<PerformanceStatsModel, PerformanceStatsId>;
|
|
60
60
|
createPerformanceStat: Sequelize.HasOneCreateAssociationMixin<PerformanceStatsModel>;
|
|
61
|
+
VPERs: VPERModel[];
|
|
62
|
+
getVPERs: Sequelize.HasManyGetAssociationsMixin<VPERModel>;
|
|
63
|
+
setVPERs: Sequelize.HasManySetAssociationsMixin<VPERModel, VPERId>;
|
|
64
|
+
addVPER: Sequelize.HasManyAddAssociationMixin<VPERModel, VPERId>;
|
|
65
|
+
addVPERs: Sequelize.HasManyAddAssociationsMixin<VPERModel, VPERId>;
|
|
66
|
+
createVPER: Sequelize.HasManyCreateAssociationMixin<VPERModel>;
|
|
67
|
+
removeVPER: Sequelize.HasManyRemoveAssociationMixin<VPERModel, VPERId>;
|
|
68
|
+
removeVPERs: Sequelize.HasManyRemoveAssociationsMixin<VPERModel, VPERId>;
|
|
69
|
+
hasVPER: Sequelize.HasManyHasAssociationMixin<VPERModel, VPERId>;
|
|
70
|
+
hasVPERs: Sequelize.HasManyHasAssociationsMixin<VPERModel, VPERId>;
|
|
71
|
+
countVPERs: Sequelize.HasManyCountAssociationsMixin;
|
|
61
72
|
PlayerTeams: PlayerTeamModel[];
|
|
62
73
|
getPlayerTeams: Sequelize.HasManyGetAssociationsMixin<PlayerTeamModel>;
|
|
63
74
|
setPlayerTeams: Sequelize.HasManySetAssociationsMixin<PlayerTeamModel, PlayerTeamId>;
|
|
@@ -3,8 +3,8 @@ import { Model } from 'sequelize';
|
|
|
3
3
|
import { MatchId, MatchModel, TeamId, TeamModel } from '..';
|
|
4
4
|
export interface MatchResultAttributes {
|
|
5
5
|
match_id: string;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
home_scores: number[];
|
|
7
|
+
away_scores: number[];
|
|
8
8
|
winner_team_id: string | null;
|
|
9
9
|
}
|
|
10
10
|
export type MatchResultPk = 'match_id';
|
|
@@ -12,8 +12,8 @@ export type MatchResultId = MatchResultModel[MatchResultPk];
|
|
|
12
12
|
export type MatchResultCreationAttributes = MatchResultAttributes;
|
|
13
13
|
export declare class MatchResultModel extends Model<MatchResultAttributes, MatchResultCreationAttributes> implements MatchResultAttributes {
|
|
14
14
|
match_id: string;
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
home_scores: number[];
|
|
16
|
+
away_scores: number[];
|
|
17
17
|
winner_team_id: string | null;
|
|
18
18
|
Match: MatchModel;
|
|
19
19
|
getMatch: Sequelize.BelongsToGetAssociationMixin<MatchModel>;
|
|
@@ -7,12 +7,12 @@ export class MatchResultModel extends Model {
|
|
|
7
7
|
allowNull: false,
|
|
8
8
|
primaryKey: true
|
|
9
9
|
},
|
|
10
|
-
|
|
11
|
-
type: DataTypes.INTEGER,
|
|
10
|
+
home_scores: {
|
|
11
|
+
type: DataTypes.ARRAY(DataTypes.INTEGER),
|
|
12
12
|
allowNull: false
|
|
13
13
|
},
|
|
14
|
-
|
|
15
|
-
type: DataTypes.INTEGER,
|
|
14
|
+
away_scores: {
|
|
15
|
+
type: DataTypes.ARRAY(DataTypes.INTEGER),
|
|
16
16
|
allowNull: false
|
|
17
17
|
},
|
|
18
18
|
winner_team_id: {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as Sequelize from 'sequelize';
|
|
2
|
+
import { Model } from 'sequelize';
|
|
3
|
+
import { MatchId, MatchModel, PlayerId, PlayerModel } from '.';
|
|
4
|
+
export interface VPERAttributes {
|
|
5
|
+
player_id: string;
|
|
6
|
+
match_id: string;
|
|
7
|
+
value: number;
|
|
8
|
+
}
|
|
9
|
+
export type VPERPk = 'player_id' | 'match_id';
|
|
10
|
+
export type VPERId = VPERModel[VPERPk];
|
|
11
|
+
export type VPERCreationAttributes = VPERAttributes;
|
|
12
|
+
export declare class VPERModel extends Model<VPERAttributes, VPERCreationAttributes> implements VPERAttributes {
|
|
13
|
+
player_id: string;
|
|
14
|
+
match_id: string;
|
|
15
|
+
value: number;
|
|
16
|
+
Player: PlayerModel;
|
|
17
|
+
getPlayer: Sequelize.BelongsToGetAssociationMixin<PlayerModel>;
|
|
18
|
+
setPlayer: Sequelize.BelongsToSetAssociationMixin<PlayerModel, PlayerId>;
|
|
19
|
+
createPlayer: Sequelize.BelongsToCreateAssociationMixin<PlayerModel>;
|
|
20
|
+
Match: MatchModel;
|
|
21
|
+
getMatch: Sequelize.BelongsToGetAssociationMixin<MatchModel>;
|
|
22
|
+
setMatch: Sequelize.BelongsToSetAssociationMixin<MatchModel, MatchId>;
|
|
23
|
+
createMatch: Sequelize.BelongsToCreateAssociationMixin<MatchModel>;
|
|
24
|
+
static initModel(sequelize: Sequelize.Sequelize): typeof VPERModel;
|
|
25
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DataTypes, Model } from 'sequelize';
|
|
2
|
+
export class VPERModel extends Model {
|
|
3
|
+
static initModel(sequelize) {
|
|
4
|
+
return VPERModel.init({
|
|
5
|
+
player_id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
allowNull: false,
|
|
8
|
+
primaryKey: true,
|
|
9
|
+
references: {
|
|
10
|
+
model: 'Player',
|
|
11
|
+
key: 'player_id'
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
match_id: {
|
|
15
|
+
type: DataTypes.UUID,
|
|
16
|
+
allowNull: false,
|
|
17
|
+
primaryKey: true,
|
|
18
|
+
references: {
|
|
19
|
+
model: 'Match',
|
|
20
|
+
key: 'match_id'
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
value: {
|
|
24
|
+
type: DataTypes.REAL,
|
|
25
|
+
allowNull: false
|
|
26
|
+
}
|
|
27
|
+
}, {
|
|
28
|
+
sequelize,
|
|
29
|
+
tableName: 'VPER',
|
|
30
|
+
schema: 'public',
|
|
31
|
+
timestamps: false,
|
|
32
|
+
indexes: [{
|
|
33
|
+
name: 'VPER_pk',
|
|
34
|
+
unique: true,
|
|
35
|
+
fields: [
|
|
36
|
+
{ name: 'player_id' },
|
|
37
|
+
{ name: 'match_id' }
|
|
38
|
+
]
|
|
39
|
+
}]
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Match } from '../../service';
|
|
2
2
|
import { transformToMatchSet } from './match-set';
|
|
3
3
|
import { transformToTeam } from './team';
|
|
4
|
+
import { transformToVPER } from './vper';
|
|
4
5
|
function transformToAttributes(match) {
|
|
5
6
|
return {
|
|
6
7
|
match_id: match.id,
|
|
@@ -13,6 +14,10 @@ function transformToAttributes(match) {
|
|
|
13
14
|
function transformToObject(model) {
|
|
14
15
|
const sets = (model.MatchSets ?? []).map(transformToMatchSet)
|
|
15
16
|
.sort((s1, s2) => s1.order - s2.order);
|
|
17
|
+
const homeScores = model.MatchResult?.home_scores ?? [];
|
|
18
|
+
const awayScores = model.MatchResult?.away_scores ?? [];
|
|
19
|
+
const sumScores = (scores) => scores.reduce((total, score) => total + score, 0);
|
|
20
|
+
const VPERs = (model.VPERs ?? []).map(transformToVPER);
|
|
16
21
|
return new Match({
|
|
17
22
|
id: model.match_id,
|
|
18
23
|
homeTeam: transformToTeam(model.HomeTeam),
|
|
@@ -20,8 +25,9 @@ function transformToObject(model) {
|
|
|
20
25
|
scheduledDate: new Date(model.scheduled_date),
|
|
21
26
|
sets,
|
|
22
27
|
status: model.status,
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
VPERs,
|
|
29
|
+
homeScore: homeScores.length > 0 ? sumScores(homeScores) : undefined,
|
|
30
|
+
awayScore: awayScores.length > 0 ? sumScores(awayScores) : undefined,
|
|
25
31
|
winner: model.MatchResult?.Winner != null ? transformToTeam(model.MatchResult.Winner) : undefined
|
|
26
32
|
});
|
|
27
33
|
}
|
|
@@ -6,7 +6,7 @@ function transformToAttributes(team) {
|
|
|
6
6
|
name: team.name,
|
|
7
7
|
short_name: team.shortName,
|
|
8
8
|
country_id: team.country?.id,
|
|
9
|
-
tactics: transformFromTactics(team.tactics, team.id),
|
|
9
|
+
tactics: team.tactics != null ? transformFromTactics(team.tactics, team.id) : undefined,
|
|
10
10
|
rating: team.rating,
|
|
11
11
|
division_id: team.divisionId
|
|
12
12
|
};
|
|
@@ -18,9 +18,9 @@ function transformToObject(model) {
|
|
|
18
18
|
name: model.name,
|
|
19
19
|
shortName: model.short_name,
|
|
20
20
|
country: transformToCountry(model.country),
|
|
21
|
-
tactics: transformToTactics(model.tactics, roster),
|
|
22
|
-
roster,
|
|
23
21
|
rating: model.rating,
|
|
22
|
+
tactics: roster != null && roster.length > 0 ? transformToTactics(model.tactics, roster) : undefined,
|
|
23
|
+
roster,
|
|
24
24
|
divisionId: model.division_id
|
|
25
25
|
});
|
|
26
26
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { VPERAttributes, VPERModel } from '../models';
|
|
2
|
+
import { VPER } from '../../service';
|
|
3
|
+
declare function transformToAttributes(vper: VPER): VPERAttributes;
|
|
4
|
+
declare function transformToObject(model: VPERModel): VPER;
|
|
5
|
+
export { transformToObject as transformToVPER, transformToAttributes as transformFromVPER };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { VPER } from '../../service';
|
|
2
|
+
function transformToAttributes(vper) {
|
|
3
|
+
return {
|
|
4
|
+
player_id: vper.playerId,
|
|
5
|
+
match_id: vper.matchId,
|
|
6
|
+
value: vper.value
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function transformToObject(model) {
|
|
10
|
+
return new VPER({
|
|
11
|
+
playerId: model.player_id,
|
|
12
|
+
matchId: model.match_id,
|
|
13
|
+
value: model.value
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export { transformToObject as transformToVPER, transformToAttributes as transformFromVPER };
|
|
@@ -2,6 +2,7 @@ import { MatchSet } from './match-set';
|
|
|
2
2
|
import { Team } from '../team';
|
|
3
3
|
import { MatchTeam } from './match-team';
|
|
4
4
|
import { StatusEnum } from '../../data';
|
|
5
|
+
import { VPER } from './vper';
|
|
5
6
|
interface MatchParams {
|
|
6
7
|
readonly id: string;
|
|
7
8
|
readonly homeTeam: Team;
|
|
@@ -9,6 +10,7 @@ interface MatchParams {
|
|
|
9
10
|
readonly scheduledDate: Date;
|
|
10
11
|
readonly sets: MatchSet[];
|
|
11
12
|
readonly status: StatusEnum;
|
|
13
|
+
readonly VPERs: VPER[];
|
|
12
14
|
homeScore?: number;
|
|
13
15
|
awayScore?: number;
|
|
14
16
|
winner?: Team;
|
|
@@ -21,11 +23,12 @@ export declare class Match {
|
|
|
21
23
|
readonly awayTeam: Team;
|
|
22
24
|
readonly sets: MatchSet[];
|
|
23
25
|
readonly scheduledDate: Date;
|
|
26
|
+
readonly VPERs: VPER[];
|
|
24
27
|
homeScore?: number;
|
|
25
28
|
awayScore?: number;
|
|
26
29
|
winner?: Team;
|
|
27
30
|
status: StatusEnum;
|
|
28
|
-
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner }: MatchParams);
|
|
31
|
+
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner, VPERs }: MatchParams);
|
|
29
32
|
addSet(set: MatchSet): void;
|
|
30
33
|
getTeamSets(team: MatchTeam): SetScore;
|
|
31
34
|
getScore(): MatchScore;
|
|
@@ -2,7 +2,7 @@ import { validateUUID } from '../utils';
|
|
|
2
2
|
import { MatchTeam } from './match-team';
|
|
3
3
|
import { StatusEnum } from '../../data';
|
|
4
4
|
export class Match {
|
|
5
|
-
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner }) {
|
|
5
|
+
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, status, homeScore, awayScore, winner, VPERs }) {
|
|
6
6
|
validateUUID(id);
|
|
7
7
|
this.id = id;
|
|
8
8
|
this.homeTeam = homeTeam;
|
|
@@ -13,6 +13,7 @@ export class Match {
|
|
|
13
13
|
this.homeScore = homeScore;
|
|
14
14
|
this.awayScore = awayScore;
|
|
15
15
|
this.winner = winner;
|
|
16
|
+
this.VPERs = VPERs;
|
|
16
17
|
}
|
|
17
18
|
addSet(set) {
|
|
18
19
|
if (this.sets.length >= 5)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BoxScore } from './box-score';
|
|
2
|
+
export interface VPERParams {
|
|
3
|
+
readonly playerId: string;
|
|
4
|
+
readonly matchId: string;
|
|
5
|
+
readonly value: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class VPER {
|
|
8
|
+
readonly playerId: string;
|
|
9
|
+
readonly matchId: string;
|
|
10
|
+
readonly value: number;
|
|
11
|
+
constructor({ playerId, matchId, value }: VPERParams);
|
|
12
|
+
static computeVPERForMatch(boxScores: BoxScore[]): number;
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const WEIGHTS = {
|
|
2
|
+
// terminal positive
|
|
3
|
+
ATTACK_KILL: 1.0,
|
|
4
|
+
SERVE_ACE: 1.0,
|
|
5
|
+
BLOCK_SOLO: 1.0,
|
|
6
|
+
BLOCK_ASSIST: 0.5,
|
|
7
|
+
// creation / continuation
|
|
8
|
+
SETTING_ASSIST: 0.7,
|
|
9
|
+
BLOCK_TOUCH: 0.2,
|
|
10
|
+
DEFENSE_DIG: 0.25,
|
|
11
|
+
SETTING_PASS: 0.15,
|
|
12
|
+
// reception quality
|
|
13
|
+
RECEPTION_PERFECT: 0.35,
|
|
14
|
+
RECEPTION_POSITIVE: 0.15,
|
|
15
|
+
RECEPTION_OVERPASS: -0.6,
|
|
16
|
+
// terminal errors (always point against)
|
|
17
|
+
TERMINAL_ERROR: -1.0
|
|
18
|
+
};
|
|
19
|
+
export class VPER {
|
|
20
|
+
constructor({ playerId, matchId, value }) {
|
|
21
|
+
this.matchId = matchId;
|
|
22
|
+
this.playerId = playerId;
|
|
23
|
+
this.value = value;
|
|
24
|
+
}
|
|
25
|
+
static computeVPERForMatch(boxScores) {
|
|
26
|
+
let rawSum = 0;
|
|
27
|
+
let pointsPlayedSum = 0;
|
|
28
|
+
for (const box of boxScores) {
|
|
29
|
+
const w = WEIGHTS;
|
|
30
|
+
const positive = w.ATTACK_KILL * box.attack.kills +
|
|
31
|
+
w.SERVE_ACE * box.serve.aces +
|
|
32
|
+
w.BLOCK_SOLO * box.block.solo +
|
|
33
|
+
w.BLOCK_ASSIST * box.block.assists +
|
|
34
|
+
w.SETTING_ASSIST * box.setting.assists +
|
|
35
|
+
w.BLOCK_TOUCH * box.block.touches +
|
|
36
|
+
w.DEFENSE_DIG * box.defense.digs +
|
|
37
|
+
w.SETTING_PASS * box.setting.pass +
|
|
38
|
+
w.RECEPTION_PERFECT * box.reception.perfect +
|
|
39
|
+
w.RECEPTION_POSITIVE * box.reception.positive;
|
|
40
|
+
const negative = w.RECEPTION_OVERPASS * box.reception.overpasses +
|
|
41
|
+
w.TERMINAL_ERROR * (box.attack.errors +
|
|
42
|
+
box.serve.errors +
|
|
43
|
+
box.reception.errors +
|
|
44
|
+
box.defense.errors +
|
|
45
|
+
box.block.errors +
|
|
46
|
+
box.setting.errors);
|
|
47
|
+
rawSum += positive + negative;
|
|
48
|
+
pointsPlayedSum += box.misc.pointsPlayed;
|
|
49
|
+
}
|
|
50
|
+
return 100 * rawSum / Math.max(1, pointsPlayedSum);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -12,7 +12,7 @@ export interface StartingLineup {
|
|
|
12
12
|
}
|
|
13
13
|
export interface TacticsOpts {
|
|
14
14
|
readonly lineup: StartingLineup;
|
|
15
|
-
readonly substitutionTolerance
|
|
15
|
+
readonly substitutionTolerance: number;
|
|
16
16
|
readonly liberoReplacements: Player[];
|
|
17
17
|
readonly pinchServerSubs: Map<Player, Player>;
|
|
18
18
|
}
|
|
@@ -9,7 +9,7 @@ interface TeamParams {
|
|
|
9
9
|
readonly divisionId: string;
|
|
10
10
|
readonly roster: Player[];
|
|
11
11
|
readonly country: Country;
|
|
12
|
-
readonly tactics
|
|
12
|
+
readonly tactics?: Tactics;
|
|
13
13
|
}
|
|
14
14
|
export declare class Team {
|
|
15
15
|
readonly id: string;
|
|
@@ -17,7 +17,7 @@ export declare class Team {
|
|
|
17
17
|
readonly name: string;
|
|
18
18
|
readonly shortName: string;
|
|
19
19
|
readonly divisionId: string;
|
|
20
|
-
readonly tactics
|
|
20
|
+
readonly tactics?: Tactics;
|
|
21
21
|
readonly country: Country;
|
|
22
22
|
private _rating;
|
|
23
23
|
constructor({ id, rating, name, shortName, divisionId, country, roster, tactics }: TeamParams);
|