volleyballsimtypes 0.0.129 → 0.0.130
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/transformers/match-rating.js +2 -2
- package/dist/cjs/src/service/competition/index.d.ts +4 -0
- package/dist/cjs/src/service/competition/index.js +6 -0
- package/dist/cjs/src/service/match/match-rating.d.ts +26 -3
- package/dist/cjs/src/service/match/match-rating.js +54 -17
- package/dist/cjs/src/service/match/match.d.ts +10 -0
- package/dist/cjs/src/service/match/match.js +19 -1
- package/dist/cjs/src/service/team/team.d.ts +1 -1
- package/dist/cjs/src/service/team/team.js +2 -5
- package/dist/esm/src/data/transformers/match-rating.js +2 -2
- package/dist/esm/src/service/competition/index.d.ts +4 -0
- package/dist/esm/src/service/competition/index.js +5 -0
- package/dist/esm/src/service/match/match-rating.d.ts +26 -3
- package/dist/esm/src/service/match/match-rating.js +55 -18
- package/dist/esm/src/service/match/match.d.ts +10 -0
- package/dist/esm/src/service/match/match.js +18 -0
- package/dist/esm/src/service/team/team.d.ts +1 -1
- package/dist/esm/src/service/team/team.js +2 -5
- package/package.json +1 -1
|
@@ -9,8 +9,8 @@ function transformToAttributes(team, rating) {
|
|
|
9
9
|
return {
|
|
10
10
|
match_id: rating.match.id,
|
|
11
11
|
team_id: teamId,
|
|
12
|
-
p: rating.
|
|
13
|
-
dR: rating.
|
|
12
|
+
p: rating.getExpectedResult(),
|
|
13
|
+
dR: rating.getPoints(team)
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
exports.transformFromMatchRating = transformToAttributes;
|
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports._CompetitionType = void 0;
|
|
17
18
|
__exportStar(require("./standing"), exports);
|
|
18
19
|
__exportStar(require("./season"), exports);
|
|
19
20
|
__exportStar(require("./league"), exports);
|
|
@@ -21,3 +22,8 @@ __exportStar(require("./iteration"), exports);
|
|
|
21
22
|
__exportStar(require("./tournament"), exports);
|
|
22
23
|
__exportStar(require("./tournament-match"), exports);
|
|
23
24
|
__exportStar(require("./stage"), exports);
|
|
25
|
+
var _CompetitionType;
|
|
26
|
+
(function (_CompetitionType) {
|
|
27
|
+
_CompetitionType["TOURNAMENT"] = "TOURNAMENT";
|
|
28
|
+
_CompetitionType["LEAGUE"] = "LEAGUE";
|
|
29
|
+
})(_CompetitionType = exports._CompetitionType || (exports._CompetitionType = {}));
|
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
import { Match, MatchTeam } from '.';
|
|
2
|
+
import { _CompetitionType } from '../competition';
|
|
2
3
|
interface MatchRatingOpts {
|
|
3
4
|
readonly match: Match;
|
|
5
|
+
readonly competitionType: _CompetitionType;
|
|
6
|
+
}
|
|
7
|
+
interface SetScoreVariant {
|
|
8
|
+
'3-0': number;
|
|
9
|
+
'3-1': number;
|
|
10
|
+
'3-2': number;
|
|
11
|
+
'2-3': number;
|
|
12
|
+
'1-3': number;
|
|
13
|
+
'0-3': number;
|
|
14
|
+
}
|
|
15
|
+
interface MatchWeightFactor {
|
|
16
|
+
TOURNAMENT: number;
|
|
17
|
+
LEAGUE: number;
|
|
4
18
|
}
|
|
5
19
|
export declare class MatchRating {
|
|
6
20
|
static K: number;
|
|
21
|
+
static SSV: SetScoreVariant;
|
|
22
|
+
static C1: number;
|
|
23
|
+
static C2: number;
|
|
24
|
+
static C3: number;
|
|
25
|
+
static C4: number;
|
|
26
|
+
static C5: number;
|
|
27
|
+
static MWF: MatchWeightFactor;
|
|
7
28
|
readonly match: Match;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
29
|
+
readonly weight: number;
|
|
30
|
+
constructor({ match, competitionType }: MatchRatingOpts);
|
|
31
|
+
getPoints(team: MatchTeam): number;
|
|
32
|
+
static calculateProbability(z: number): number;
|
|
33
|
+
getExpectedResult(): number;
|
|
11
34
|
}
|
|
12
35
|
export {};
|
|
@@ -2,28 +2,65 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MatchRating = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
|
+
const competition_1 = require("../competition");
|
|
5
6
|
class MatchRating {
|
|
6
|
-
constructor({ match }) {
|
|
7
|
+
constructor({ match, competitionType }) {
|
|
7
8
|
this.match = match;
|
|
9
|
+
this.weight = MatchRating.MWF[competitionType];
|
|
8
10
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
getPoints(team) {
|
|
12
|
+
const rankingValue = MatchRating.SSV[this.match.getScore()] - this.getExpectedResult();
|
|
13
|
+
const weighted = rankingValue * this.weight / MatchRating.K;
|
|
14
|
+
if (this.match.isWinner(team))
|
|
15
|
+
return weighted;
|
|
16
|
+
else
|
|
17
|
+
return weighted * -1;
|
|
18
|
+
}
|
|
19
|
+
static calculateProbability(z) {
|
|
20
|
+
let area = 0.0;
|
|
21
|
+
const rectangles = 100000;
|
|
22
|
+
const width = (z - (-10)) / rectangles;
|
|
23
|
+
for (let i = 0; i < rectangles; i++) {
|
|
24
|
+
area += width * Math.exp(-Math.pow((width * i + (-10)), 2) / 2) / Math.sqrt(2 * Math.PI);
|
|
19
25
|
}
|
|
20
|
-
return
|
|
26
|
+
return area;
|
|
21
27
|
}
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
28
|
+
getExpectedResult() {
|
|
29
|
+
const D = MatchRating.K * (this.match.homeTeam.rating - this.match.awayTeam.rating) / 1000; // Strength difference between the teams
|
|
30
|
+
const P1 = MatchRating.calculateProbability(MatchRating.C1 + D); // 3-0
|
|
31
|
+
const P2 = MatchRating.calculateProbability(MatchRating.C2 + D) -
|
|
32
|
+
MatchRating.calculateProbability(MatchRating.C1 + D); // 3-1
|
|
33
|
+
const P3 = MatchRating.calculateProbability(MatchRating.C3 + D) -
|
|
34
|
+
MatchRating.calculateProbability(MatchRating.C2 + D); // 3-2
|
|
35
|
+
const P4 = MatchRating.calculateProbability(MatchRating.C4 + D) -
|
|
36
|
+
MatchRating.calculateProbability(MatchRating.C3 + D); // 2-3
|
|
37
|
+
const P5 = MatchRating.calculateProbability(MatchRating.C5 + D) -
|
|
38
|
+
MatchRating.calculateProbability(MatchRating.C4 + D); // 1-3
|
|
39
|
+
const P6 = 1 - MatchRating.calculateProbability(MatchRating.C5 + D); // 0-3
|
|
40
|
+
return P1 * MatchRating.SSV['3-0'] +
|
|
41
|
+
P2 * MatchRating.SSV['3-1'] +
|
|
42
|
+
P3 * MatchRating.SSV['3-2'] +
|
|
43
|
+
P4 * MatchRating.SSV['2-3'] +
|
|
44
|
+
P5 * MatchRating.SSV['1-3'] +
|
|
45
|
+
P6 * MatchRating.SSV['0-3']; // Expected Match Result EMR
|
|
26
46
|
}
|
|
27
47
|
}
|
|
28
48
|
exports.MatchRating = MatchRating;
|
|
29
|
-
MatchRating.K =
|
|
49
|
+
MatchRating.K = 8; // Standard scaling factor
|
|
50
|
+
MatchRating.SSV = {
|
|
51
|
+
[_1.MatchScore['3-0']]: 2,
|
|
52
|
+
[_1.MatchScore['3-1']]: 1.5,
|
|
53
|
+
[_1.MatchScore['3-2']]: 1,
|
|
54
|
+
[_1.MatchScore['2-3']]: -1,
|
|
55
|
+
[_1.MatchScore['1-3']]: -1.5,
|
|
56
|
+
[_1.MatchScore['0-3']]: -2
|
|
57
|
+
};
|
|
58
|
+
MatchRating.C1 = -1.060;
|
|
59
|
+
MatchRating.C2 = -0.394;
|
|
60
|
+
MatchRating.C3 = 0;
|
|
61
|
+
MatchRating.C4 = 0.394;
|
|
62
|
+
MatchRating.C5 = 1.060;
|
|
63
|
+
MatchRating.MWF = {
|
|
64
|
+
[competition_1._CompetitionType.TOURNAMENT]: 50,
|
|
65
|
+
[competition_1._CompetitionType.LEAGUE]: 35
|
|
66
|
+
};
|
|
@@ -9,6 +9,14 @@ interface MatchOpts {
|
|
|
9
9
|
readonly sets: MatchSet[];
|
|
10
10
|
readonly isSimulated: boolean;
|
|
11
11
|
}
|
|
12
|
+
export declare enum MatchScore {
|
|
13
|
+
'3-0' = "3-0",
|
|
14
|
+
'3-1' = "3-1",
|
|
15
|
+
'3-2' = "3-2",
|
|
16
|
+
'2-3' = "2-3",
|
|
17
|
+
'1-3' = "1-3",
|
|
18
|
+
'0-3' = "0-3"
|
|
19
|
+
}
|
|
12
20
|
export declare class Match {
|
|
13
21
|
static readonly BEST_OF = 5;
|
|
14
22
|
readonly id: string;
|
|
@@ -20,7 +28,9 @@ export declare class Match {
|
|
|
20
28
|
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, isSimulated }: MatchOpts);
|
|
21
29
|
addSet(set: MatchSet): void;
|
|
22
30
|
getTeamSets(team: MatchTeam): number;
|
|
31
|
+
getScore(): MatchScore;
|
|
23
32
|
isOver(): boolean;
|
|
24
33
|
getWinner(): Team;
|
|
34
|
+
isWinner(team: MatchTeam): boolean;
|
|
25
35
|
}
|
|
26
36
|
export {};
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Match = void 0;
|
|
3
|
+
exports.Match = exports.MatchScore = void 0;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
5
|
const match_team_1 = require("./match-team");
|
|
6
|
+
var MatchScore;
|
|
7
|
+
(function (MatchScore) {
|
|
8
|
+
MatchScore["3-0"] = "3-0";
|
|
9
|
+
MatchScore["3-1"] = "3-1";
|
|
10
|
+
MatchScore["3-2"] = "3-2";
|
|
11
|
+
MatchScore["2-3"] = "2-3";
|
|
12
|
+
MatchScore["1-3"] = "1-3";
|
|
13
|
+
MatchScore["0-3"] = "0-3";
|
|
14
|
+
})(MatchScore = exports.MatchScore || (exports.MatchScore = {}));
|
|
6
15
|
class Match {
|
|
7
16
|
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, isSimulated }) {
|
|
8
17
|
(0, utils_1.validateUUID)(id);
|
|
@@ -21,6 +30,9 @@ class Match {
|
|
|
21
30
|
getTeamSets(team) {
|
|
22
31
|
return this.sets.reduce((sets, set) => sets + (!set.isOver() ? 0 : set.getWinner() === team ? 1 : 0), 0);
|
|
23
32
|
}
|
|
33
|
+
getScore() {
|
|
34
|
+
return `${this.getTeamSets(match_team_1.MatchTeam.HOME)}-${this.getTeamSets(match_team_1.MatchTeam.AWAY)}`;
|
|
35
|
+
}
|
|
24
36
|
isOver() {
|
|
25
37
|
const gamesRequired = Math.ceil(Match.BEST_OF / 2);
|
|
26
38
|
const lastSet = this.sets.at(-1);
|
|
@@ -38,6 +50,12 @@ class Match {
|
|
|
38
50
|
const awaySets = this.getTeamSets(match_team_1.MatchTeam.AWAY);
|
|
39
51
|
return homeSets > awaySets ? this.homeTeam : this.awayTeam;
|
|
40
52
|
}
|
|
53
|
+
isWinner(team) {
|
|
54
|
+
if (team === match_team_1.MatchTeam.HOME && this.getWinner() === this.homeTeam)
|
|
55
|
+
return true;
|
|
56
|
+
else
|
|
57
|
+
return team === match_team_1.MatchTeam.AWAY && this.getWinner() === this.awayTeam;
|
|
58
|
+
}
|
|
41
59
|
}
|
|
42
60
|
exports.Match = Match;
|
|
43
61
|
Match.BEST_OF = 5;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Team = void 0;
|
|
4
4
|
const utils_1 = require("../utils");
|
|
5
|
-
const match_1 = require("../match");
|
|
6
5
|
class Team {
|
|
7
6
|
constructor({ id, rating, name, shortName, country, roster, coach, league }) {
|
|
8
7
|
(0, utils_1.validateUUID)(id);
|
|
@@ -30,10 +29,8 @@ class Team {
|
|
|
30
29
|
}
|
|
31
30
|
return `${this.name} [${this.shortName}] (${this.country?.name}) ELO=${this._rating}`;
|
|
32
31
|
}
|
|
33
|
-
updateRating(
|
|
34
|
-
|
|
35
|
-
throw new Error(`INVALID RATING CHANGE: ${ratingChange}`);
|
|
36
|
-
this._rating += ratingChange;
|
|
32
|
+
updateRating(rankingPoints) {
|
|
33
|
+
this._rating += rankingPoints;
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
exports.Team = Team;
|
|
@@ -6,8 +6,8 @@ function transformToAttributes(team, rating) {
|
|
|
6
6
|
return {
|
|
7
7
|
match_id: rating.match.id,
|
|
8
8
|
team_id: teamId,
|
|
9
|
-
p: rating.
|
|
10
|
-
dR: rating.
|
|
9
|
+
p: rating.getExpectedResult(),
|
|
10
|
+
dR: rating.getPoints(team)
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
export { transformToAttributes as transformFromMatchRating };
|
|
@@ -5,3 +5,8 @@ export * from './iteration';
|
|
|
5
5
|
export * from './tournament';
|
|
6
6
|
export * from './tournament-match';
|
|
7
7
|
export * from './stage';
|
|
8
|
+
export var _CompetitionType;
|
|
9
|
+
(function (_CompetitionType) {
|
|
10
|
+
_CompetitionType["TOURNAMENT"] = "TOURNAMENT";
|
|
11
|
+
_CompetitionType["LEAGUE"] = "LEAGUE";
|
|
12
|
+
})(_CompetitionType || (_CompetitionType = {}));
|
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
import { Match, MatchTeam } from '.';
|
|
2
|
+
import { _CompetitionType } from '../competition';
|
|
2
3
|
interface MatchRatingOpts {
|
|
3
4
|
readonly match: Match;
|
|
5
|
+
readonly competitionType: _CompetitionType;
|
|
6
|
+
}
|
|
7
|
+
interface SetScoreVariant {
|
|
8
|
+
'3-0': number;
|
|
9
|
+
'3-1': number;
|
|
10
|
+
'3-2': number;
|
|
11
|
+
'2-3': number;
|
|
12
|
+
'1-3': number;
|
|
13
|
+
'0-3': number;
|
|
14
|
+
}
|
|
15
|
+
interface MatchWeightFactor {
|
|
16
|
+
TOURNAMENT: number;
|
|
17
|
+
LEAGUE: number;
|
|
4
18
|
}
|
|
5
19
|
export declare class MatchRating {
|
|
6
20
|
static K: number;
|
|
21
|
+
static SSV: SetScoreVariant;
|
|
22
|
+
static C1: number;
|
|
23
|
+
static C2: number;
|
|
24
|
+
static C3: number;
|
|
25
|
+
static C4: number;
|
|
26
|
+
static C5: number;
|
|
27
|
+
static MWF: MatchWeightFactor;
|
|
7
28
|
readonly match: Match;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
29
|
+
readonly weight: number;
|
|
30
|
+
constructor({ match, competitionType }: MatchRatingOpts);
|
|
31
|
+
getPoints(team: MatchTeam): number;
|
|
32
|
+
static calculateProbability(z: number): number;
|
|
33
|
+
getExpectedResult(): number;
|
|
11
34
|
}
|
|
12
35
|
export {};
|
|
@@ -1,25 +1,62 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MatchScore } from '.';
|
|
2
|
+
import { _CompetitionType } from '../competition';
|
|
2
3
|
export class MatchRating {
|
|
3
|
-
constructor({ match }) {
|
|
4
|
+
constructor({ match, competitionType }) {
|
|
4
5
|
this.match = match;
|
|
6
|
+
this.weight = MatchRating.MWF[competitionType];
|
|
5
7
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (team
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
getPoints(team) {
|
|
9
|
+
const rankingValue = MatchRating.SSV[this.match.getScore()] - this.getExpectedResult();
|
|
10
|
+
const weighted = rankingValue * this.weight / MatchRating.K;
|
|
11
|
+
if (this.match.isWinner(team))
|
|
12
|
+
return weighted;
|
|
13
|
+
else
|
|
14
|
+
return weighted * -1;
|
|
15
|
+
}
|
|
16
|
+
static calculateProbability(z) {
|
|
17
|
+
let area = 0.0;
|
|
18
|
+
const rectangles = 100000;
|
|
19
|
+
const width = (z - (-10)) / rectangles;
|
|
20
|
+
for (let i = 0; i < rectangles; i++) {
|
|
21
|
+
area += width * Math.exp(-Math.pow((width * i + (-10)), 2) / 2) / Math.sqrt(2 * Math.PI);
|
|
16
22
|
}
|
|
17
|
-
return
|
|
23
|
+
return area;
|
|
18
24
|
}
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
25
|
+
getExpectedResult() {
|
|
26
|
+
const D = MatchRating.K * (this.match.homeTeam.rating - this.match.awayTeam.rating) / 1000; // Strength difference between the teams
|
|
27
|
+
const P1 = MatchRating.calculateProbability(MatchRating.C1 + D); // 3-0
|
|
28
|
+
const P2 = MatchRating.calculateProbability(MatchRating.C2 + D) -
|
|
29
|
+
MatchRating.calculateProbability(MatchRating.C1 + D); // 3-1
|
|
30
|
+
const P3 = MatchRating.calculateProbability(MatchRating.C3 + D) -
|
|
31
|
+
MatchRating.calculateProbability(MatchRating.C2 + D); // 3-2
|
|
32
|
+
const P4 = MatchRating.calculateProbability(MatchRating.C4 + D) -
|
|
33
|
+
MatchRating.calculateProbability(MatchRating.C3 + D); // 2-3
|
|
34
|
+
const P5 = MatchRating.calculateProbability(MatchRating.C5 + D) -
|
|
35
|
+
MatchRating.calculateProbability(MatchRating.C4 + D); // 1-3
|
|
36
|
+
const P6 = 1 - MatchRating.calculateProbability(MatchRating.C5 + D); // 0-3
|
|
37
|
+
return P1 * MatchRating.SSV['3-0'] +
|
|
38
|
+
P2 * MatchRating.SSV['3-1'] +
|
|
39
|
+
P3 * MatchRating.SSV['3-2'] +
|
|
40
|
+
P4 * MatchRating.SSV['2-3'] +
|
|
41
|
+
P5 * MatchRating.SSV['1-3'] +
|
|
42
|
+
P6 * MatchRating.SSV['0-3']; // Expected Match Result EMR
|
|
23
43
|
}
|
|
24
44
|
}
|
|
25
|
-
MatchRating.K =
|
|
45
|
+
MatchRating.K = 8; // Standard scaling factor
|
|
46
|
+
MatchRating.SSV = {
|
|
47
|
+
[MatchScore['3-0']]: 2,
|
|
48
|
+
[MatchScore['3-1']]: 1.5,
|
|
49
|
+
[MatchScore['3-2']]: 1,
|
|
50
|
+
[MatchScore['2-3']]: -1,
|
|
51
|
+
[MatchScore['1-3']]: -1.5,
|
|
52
|
+
[MatchScore['0-3']]: -2
|
|
53
|
+
};
|
|
54
|
+
MatchRating.C1 = -1.060;
|
|
55
|
+
MatchRating.C2 = -0.394;
|
|
56
|
+
MatchRating.C3 = 0;
|
|
57
|
+
MatchRating.C4 = 0.394;
|
|
58
|
+
MatchRating.C5 = 1.060;
|
|
59
|
+
MatchRating.MWF = {
|
|
60
|
+
[_CompetitionType.TOURNAMENT]: 50,
|
|
61
|
+
[_CompetitionType.LEAGUE]: 35
|
|
62
|
+
};
|
|
@@ -9,6 +9,14 @@ interface MatchOpts {
|
|
|
9
9
|
readonly sets: MatchSet[];
|
|
10
10
|
readonly isSimulated: boolean;
|
|
11
11
|
}
|
|
12
|
+
export declare enum MatchScore {
|
|
13
|
+
'3-0' = "3-0",
|
|
14
|
+
'3-1' = "3-1",
|
|
15
|
+
'3-2' = "3-2",
|
|
16
|
+
'2-3' = "2-3",
|
|
17
|
+
'1-3' = "1-3",
|
|
18
|
+
'0-3' = "0-3"
|
|
19
|
+
}
|
|
12
20
|
export declare class Match {
|
|
13
21
|
static readonly BEST_OF = 5;
|
|
14
22
|
readonly id: string;
|
|
@@ -20,7 +28,9 @@ export declare class Match {
|
|
|
20
28
|
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, isSimulated }: MatchOpts);
|
|
21
29
|
addSet(set: MatchSet): void;
|
|
22
30
|
getTeamSets(team: MatchTeam): number;
|
|
31
|
+
getScore(): MatchScore;
|
|
23
32
|
isOver(): boolean;
|
|
24
33
|
getWinner(): Team;
|
|
34
|
+
isWinner(team: MatchTeam): boolean;
|
|
25
35
|
}
|
|
26
36
|
export {};
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { validateUUID } from '../utils';
|
|
2
2
|
import { MatchTeam } from './match-team';
|
|
3
|
+
export var MatchScore;
|
|
4
|
+
(function (MatchScore) {
|
|
5
|
+
MatchScore["3-0"] = "3-0";
|
|
6
|
+
MatchScore["3-1"] = "3-1";
|
|
7
|
+
MatchScore["3-2"] = "3-2";
|
|
8
|
+
MatchScore["2-3"] = "2-3";
|
|
9
|
+
MatchScore["1-3"] = "1-3";
|
|
10
|
+
MatchScore["0-3"] = "0-3";
|
|
11
|
+
})(MatchScore || (MatchScore = {}));
|
|
3
12
|
export class Match {
|
|
4
13
|
constructor({ id, homeTeam, awayTeam, scheduledDate, sets, isSimulated }) {
|
|
5
14
|
validateUUID(id);
|
|
@@ -18,6 +27,9 @@ export class Match {
|
|
|
18
27
|
getTeamSets(team) {
|
|
19
28
|
return this.sets.reduce((sets, set) => sets + (!set.isOver() ? 0 : set.getWinner() === team ? 1 : 0), 0);
|
|
20
29
|
}
|
|
30
|
+
getScore() {
|
|
31
|
+
return `${this.getTeamSets(MatchTeam.HOME)}-${this.getTeamSets(MatchTeam.AWAY)}`;
|
|
32
|
+
}
|
|
21
33
|
isOver() {
|
|
22
34
|
const gamesRequired = Math.ceil(Match.BEST_OF / 2);
|
|
23
35
|
const lastSet = this.sets.at(-1);
|
|
@@ -35,5 +47,11 @@ export class Match {
|
|
|
35
47
|
const awaySets = this.getTeamSets(MatchTeam.AWAY);
|
|
36
48
|
return homeSets > awaySets ? this.homeTeam : this.awayTeam;
|
|
37
49
|
}
|
|
50
|
+
isWinner(team) {
|
|
51
|
+
if (team === MatchTeam.HOME && this.getWinner() === this.homeTeam)
|
|
52
|
+
return true;
|
|
53
|
+
else
|
|
54
|
+
return team === MatchTeam.AWAY && this.getWinner() === this.awayTeam;
|
|
55
|
+
}
|
|
38
56
|
}
|
|
39
57
|
Match.BEST_OF = 5;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { validateUUID } from '../utils';
|
|
2
|
-
import { MatchRating } from '../match';
|
|
3
2
|
export class Team {
|
|
4
3
|
constructor({ id, rating, name, shortName, country, roster, coach, league }) {
|
|
5
4
|
validateUUID(id);
|
|
@@ -27,9 +26,7 @@ export class Team {
|
|
|
27
26
|
}
|
|
28
27
|
return `${this.name} [${this.shortName}] (${this.country?.name}) ELO=${this._rating}`;
|
|
29
28
|
}
|
|
30
|
-
updateRating(
|
|
31
|
-
|
|
32
|
-
throw new Error(`INVALID RATING CHANGE: ${ratingChange}`);
|
|
33
|
-
this._rating += ratingChange;
|
|
29
|
+
updateRating(rankingPoints) {
|
|
30
|
+
this._rating += rankingPoints;
|
|
34
31
|
}
|
|
35
32
|
}
|