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.
Files changed (49) hide show
  1. package/dist/cjs/src/data/init-models.js +7 -1
  2. package/dist/cjs/src/data/models/index.d.ts +1 -0
  3. package/dist/cjs/src/data/models/index.js +1 -0
  4. package/dist/cjs/src/data/models/match.d.ts +13 -1
  5. package/dist/cjs/src/data/models/player.d.ts +12 -1
  6. package/dist/cjs/src/data/models/views/match-result.d.ts +4 -4
  7. package/dist/cjs/src/data/models/views/match-result.js +4 -4
  8. package/dist/cjs/src/data/models/vper.d.ts +25 -0
  9. package/dist/cjs/src/data/models/vper.js +46 -0
  10. package/dist/cjs/src/data/transformers/index.d.ts +1 -0
  11. package/dist/cjs/src/data/transformers/index.js +1 -0
  12. package/dist/cjs/src/data/transformers/match.js +8 -2
  13. package/dist/cjs/src/data/transformers/team.js +3 -3
  14. package/dist/cjs/src/data/transformers/vper.d.ts +5 -0
  15. package/dist/cjs/src/data/transformers/vper.js +20 -0
  16. package/dist/cjs/src/service/match/index.d.ts +1 -0
  17. package/dist/cjs/src/service/match/index.js +1 -0
  18. package/dist/cjs/src/service/match/match.d.ts +4 -1
  19. package/dist/cjs/src/service/match/match.js +2 -1
  20. package/dist/cjs/src/service/match/vper.d.ts +13 -0
  21. package/dist/cjs/src/service/match/vper.js +56 -0
  22. package/dist/cjs/src/service/team/tactics.d.ts +1 -1
  23. package/dist/cjs/src/service/team/team.d.ts +2 -2
  24. package/dist/cjs/src/service/utils/object-utils.d.ts +3 -0
  25. package/dist/esm/src/data/init-models.js +8 -2
  26. package/dist/esm/src/data/models/index.d.ts +1 -0
  27. package/dist/esm/src/data/models/index.js +1 -0
  28. package/dist/esm/src/data/models/match.d.ts +13 -1
  29. package/dist/esm/src/data/models/player.d.ts +12 -1
  30. package/dist/esm/src/data/models/views/match-result.d.ts +4 -4
  31. package/dist/esm/src/data/models/views/match-result.js +4 -4
  32. package/dist/esm/src/data/models/vper.d.ts +25 -0
  33. package/dist/esm/src/data/models/vper.js +42 -0
  34. package/dist/esm/src/data/transformers/index.d.ts +1 -0
  35. package/dist/esm/src/data/transformers/index.js +1 -0
  36. package/dist/esm/src/data/transformers/match.js +8 -2
  37. package/dist/esm/src/data/transformers/team.js +3 -3
  38. package/dist/esm/src/data/transformers/vper.d.ts +5 -0
  39. package/dist/esm/src/data/transformers/vper.js +16 -0
  40. package/dist/esm/src/service/match/index.d.ts +1 -0
  41. package/dist/esm/src/service/match/index.js +1 -0
  42. package/dist/esm/src/service/match/match.d.ts +4 -1
  43. package/dist/esm/src/service/match/match.js +2 -1
  44. package/dist/esm/src/service/match/vper.d.ts +13 -0
  45. package/dist/esm/src/service/match/vper.js +52 -0
  46. package/dist/esm/src/service/team/tactics.d.ts +1 -1
  47. package/dist/esm/src/service/team/team.d.ts +2 -2
  48. package/dist/esm/src/service/utils/object-utils.d.ts +3 -0
  49. 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;
@@ -20,4 +20,5 @@ export * from './rally';
20
20
  export * from './team';
21
21
  export * from './user';
22
22
  export * from './tactics';
23
+ export * from './vper';
23
24
  export * from './views';
@@ -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
- home_score: number;
7
- away_score: number;
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
- home_score: number;
16
- away_score: number;
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
- home_score: {
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
- away_score: {
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;
@@ -20,3 +20,4 @@ export * from './player-team';
20
20
  export * from './match-rating';
21
21
  export * from './team';
22
22
  export * from './tactics';
23
+ export * from './vper';
@@ -36,3 +36,4 @@ __exportStar(require("./player-team"), exports);
36
36
  __exportStar(require("./match-rating"), exports);
37
37
  __exportStar(require("./team"), exports);
38
38
  __exportStar(require("./tactics"), exports);
39
+ __exportStar(require("./vper"), exports);
@@ -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
- homeScore: model.MatchResult?.home_score,
28
- awayScore: model.MatchResult?.away_score,
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;
@@ -5,3 +5,4 @@ export * from './match-set';
5
5
  export * from './rally';
6
6
  export * from './court-position';
7
7
  export * from './match-team';
8
+ export * from './vper';
@@ -21,3 +21,4 @@ __exportStar(require("./match-set"), exports);
21
21
  __exportStar(require("./rally"), exports);
22
22
  __exportStar(require("./court-position"), exports);
23
23
  __exportStar(require("./match-team"), exports);
24
+ __exportStar(require("./vper"), exports);
@@ -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?: number;
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: 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: 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 +1,4 @@
1
1
  export declare const getKeys: <T extends object>(obj: T) => (keyof T)[];
2
+ export type DataProps<T> = {
3
+ [K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K];
4
+ };
@@ -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
  }
@@ -20,4 +20,5 @@ export * from './rally';
20
20
  export * from './team';
21
21
  export * from './user';
22
22
  export * from './tactics';
23
+ export * from './vper';
23
24
  export * from './views';
@@ -20,4 +20,5 @@ export * from './rally';
20
20
  export * from './team';
21
21
  export * from './user';
22
22
  export * from './tactics';
23
+ export * from './vper';
23
24
  export * from './views';
@@ -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
- home_score: number;
7
- away_score: number;
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
- home_score: number;
16
- away_score: number;
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
- home_score: {
11
- type: DataTypes.INTEGER,
10
+ home_scores: {
11
+ type: DataTypes.ARRAY(DataTypes.INTEGER),
12
12
  allowNull: false
13
13
  },
14
- away_score: {
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
+ }
@@ -20,3 +20,4 @@ export * from './player-team';
20
20
  export * from './match-rating';
21
21
  export * from './team';
22
22
  export * from './tactics';
23
+ export * from './vper';
@@ -20,3 +20,4 @@ export * from './player-team';
20
20
  export * from './match-rating';
21
21
  export * from './team';
22
22
  export * from './tactics';
23
+ export * from './vper';
@@ -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
- homeScore: model.MatchResult?.home_score,
24
- awayScore: model.MatchResult?.away_score,
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 };
@@ -5,3 +5,4 @@ export * from './match-set';
5
5
  export * from './rally';
6
6
  export * from './court-position';
7
7
  export * from './match-team';
8
+ export * from './vper';
@@ -5,3 +5,4 @@ export * from './match-set';
5
5
  export * from './rally';
6
6
  export * from './court-position';
7
7
  export * from './match-team';
8
+ export * from './vper';
@@ -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?: number;
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: 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: 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 +1,4 @@
1
1
  export declare const getKeys: <T extends object>(obj: T) => (keyof T)[];
2
+ export type DataProps<T> = {
3
+ [K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K];
4
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "volleyballsimtypes",
3
- "version": "0.0.205",
3
+ "version": "0.0.207",
4
4
  "description": "vbsim types",
5
5
  "main": "./dist/cjs/src/index.js",
6
6
  "module": "./dist/esm/src/index.js",