overtime-live-trading-utils 2.1.32 → 2.1.33
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/.circleci/config.yml +32 -32
- package/.prettierrc +9 -9
- package/CLAUDE.md +77 -0
- package/codecov.yml +20 -20
- package/index.ts +26 -26
- package/jest.config.ts +16 -16
- package/main.js +1 -1
- package/package.json +30 -30
- package/resolution_live_markets.md +351 -0
- package/src/constants/common.ts +7 -7
- package/src/constants/errors.ts +6 -6
- package/src/constants/sports.ts +78 -78
- package/src/enums/sports.ts +109 -109
- package/src/tests/mock/MockLeagueMap.ts +170 -170
- package/src/tests/mock/MockOpticOddsEvents.ts +518 -518
- package/src/tests/mock/MockOpticSoccer.ts +9378 -9378
- package/src/tests/mock/MockSoccerRedis.ts +2308 -2308
- package/src/tests/unit/bookmakers.test.ts +79 -79
- package/src/tests/unit/markets.test.ts +156 -156
- package/src/tests/unit/odds.test.ts +92 -92
- package/src/tests/unit/resolution.test.ts +993 -935
- package/src/tests/unit/sports.test.ts +58 -58
- package/src/tests/unit/spread.test.ts +131 -131
- package/src/types/missing-types.d.ts +2 -2
- package/src/types/odds.ts +61 -61
- package/src/types/resolution.ts +96 -96
- package/src/types/sports.ts +19 -19
- package/src/utils/bookmakers.ts +159 -159
- package/src/utils/constraints.ts +210 -210
- package/src/utils/gameMatching.ts +81 -81
- package/src/utils/markets.ts +119 -119
- package/src/utils/odds.ts +918 -918
- package/src/utils/opticOdds.ts +71 -71
- package/src/utils/resolution.ts +298 -291
- package/src/utils/sports.ts +51 -51
- package/src/utils/spread.ts +97 -97
- package/tsconfig.json +16 -16
- package/webpack.config.js +24 -24
package/src/utils/constraints.ts
CHANGED
|
@@ -1,210 +1,210 @@
|
|
|
1
|
-
import { League, Sport, getLeagueSport } from 'overtime-utils';
|
|
2
|
-
import { ScoresObject } from '../types/odds';
|
|
3
|
-
|
|
4
|
-
export const checkGameContraints = (
|
|
5
|
-
opticOddsScoresApiResponse: ScoresObject,
|
|
6
|
-
marketLeague: League,
|
|
7
|
-
constraintsMap: Map<Sport, number>
|
|
8
|
-
) => {
|
|
9
|
-
const marketSport = getLeagueSport(marketLeague);
|
|
10
|
-
const homeTeam = opticOddsScoresApiResponse.homeTeam;
|
|
11
|
-
const awayTeam = opticOddsScoresApiResponse.awayTeam;
|
|
12
|
-
|
|
13
|
-
const currentClock = opticOddsScoresApiResponse.clock;
|
|
14
|
-
const currentPeriod = opticOddsScoresApiResponse.period;
|
|
15
|
-
const currentGameStatus = opticOddsScoresApiResponse.status;
|
|
16
|
-
|
|
17
|
-
if (currentGameStatus.toLowerCase() == 'completed') {
|
|
18
|
-
return {
|
|
19
|
-
allow: false,
|
|
20
|
-
message: `Blocking game ${homeTeam} - ${awayTeam} because it is no longer live.`,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if (marketSport === Sport.SOCCER) {
|
|
25
|
-
return allowSoccerGame(homeTeam, awayTeam, currentClock, currentPeriod, constraintsMap.get(Sport.SOCCER));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
allow: true,
|
|
30
|
-
message: `The sport ${marketLeague} does not have constraint`,
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const allowGameSportWithPeriodConstraint = (
|
|
35
|
-
homeTeam: string,
|
|
36
|
-
awayTeam: string,
|
|
37
|
-
currentPeriod: number,
|
|
38
|
-
periodLimitForLiveTrade: number
|
|
39
|
-
) => {
|
|
40
|
-
if (!Number.isNaN(currentPeriod) && currentPeriod >= periodLimitForLiveTrade) {
|
|
41
|
-
return {
|
|
42
|
-
allow: false,
|
|
43
|
-
message: `Blocking game ${homeTeam} - ${awayTeam} due to period: ${currentPeriod}. period`,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
return { allow: true, message: '' };
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export const allowSoccerGame = (
|
|
50
|
-
homeTeam: string,
|
|
51
|
-
awayTeam: string,
|
|
52
|
-
currentClock: string,
|
|
53
|
-
currentPeriod: string,
|
|
54
|
-
soccerMinuteLimitForLiveTrading: number | undefined
|
|
55
|
-
) => {
|
|
56
|
-
const currentClockNumber = Number(currentClock);
|
|
57
|
-
if (
|
|
58
|
-
(!Number.isNaN(currentClockNumber) &&
|
|
59
|
-
soccerMinuteLimitForLiveTrading !== undefined &&
|
|
60
|
-
currentClockNumber >= soccerMinuteLimitForLiveTrading) ||
|
|
61
|
-
(Number.isNaN(currentClockNumber) && currentPeriod.toLowerCase() != 'half')
|
|
62
|
-
) {
|
|
63
|
-
return { allow: false, message: `Blocking game ${homeTeam} - ${awayTeam} due to clock: ${currentClock}min` };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return { allow: true, message: '' };
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export const allowGameSportWithResultConstraint = (
|
|
70
|
-
opticOddsScoresApiResponse: ScoresObject,
|
|
71
|
-
homeTeam: string,
|
|
72
|
-
awayTeam: string,
|
|
73
|
-
currentPeriod: string,
|
|
74
|
-
currentScoreHome: number,
|
|
75
|
-
currentScoreAway: number,
|
|
76
|
-
marketLeague: League,
|
|
77
|
-
marketSport: Sport
|
|
78
|
-
) => {
|
|
79
|
-
const setInProgress = Number(currentPeriod);
|
|
80
|
-
const currentResultInSet = fetchResultInCurrentSet(setInProgress, opticOddsScoresApiResponse);
|
|
81
|
-
const atpGrandSlamMatch = opticOddsScoresApiResponse.league.toLowerCase() == 'atp';
|
|
82
|
-
const currentSetsScore = { home: currentScoreHome, away: currentScoreAway };
|
|
83
|
-
|
|
84
|
-
if (marketSport == Sport.VOLLEYBALL) {
|
|
85
|
-
if (setInProgress == 5) {
|
|
86
|
-
return checkResultConstraint(
|
|
87
|
-
homeTeam,
|
|
88
|
-
awayTeam,
|
|
89
|
-
currentResultInSet,
|
|
90
|
-
currentSetsScore,
|
|
91
|
-
VOLLEYBALL_SET_THRESHOLD,
|
|
92
|
-
VOLLEYBALL_FIFTH_SET_POINTS_LIMIT
|
|
93
|
-
);
|
|
94
|
-
} else {
|
|
95
|
-
return checkResultConstraint(
|
|
96
|
-
homeTeam,
|
|
97
|
-
awayTeam,
|
|
98
|
-
currentResultInSet,
|
|
99
|
-
currentSetsScore,
|
|
100
|
-
VOLLEYBALL_SET_THRESHOLD,
|
|
101
|
-
VOLLEYBALL_POINTS_LIMIT
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (marketLeague.toString().startsWith(League.TENNIS_GS.toString()) && atpGrandSlamMatch) {
|
|
107
|
-
return checkResultConstraint(
|
|
108
|
-
homeTeam,
|
|
109
|
-
awayTeam,
|
|
110
|
-
currentResultInSet,
|
|
111
|
-
currentSetsScore,
|
|
112
|
-
TENNIS_ATP_GRAND_SLAM_SET_THRESHOLD,
|
|
113
|
-
TENNIS_GEMS_LIMIT
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
(marketLeague.toString().startsWith(League.TENNIS_GS.toString()) && !atpGrandSlamMatch) ||
|
|
119
|
-
marketLeague.toString().startsWith(League.TENNIS_MASTERS.toString()) ||
|
|
120
|
-
marketLeague.toString().startsWith(League.SUMMER_OLYMPICS_TENNIS.toString()) ||
|
|
121
|
-
marketLeague.toString().startsWith(League.TENNIS_WTA.toString()) ||
|
|
122
|
-
marketLeague.toString().startsWith(League.TENNIS_ATP_CHALLENGER.toString())
|
|
123
|
-
) {
|
|
124
|
-
return checkResultConstraint(
|
|
125
|
-
homeTeam,
|
|
126
|
-
awayTeam,
|
|
127
|
-
currentResultInSet,
|
|
128
|
-
currentSetsScore,
|
|
129
|
-
TENNIS_MASTERS_SET_THRESHOLD,
|
|
130
|
-
TENNIS_GEMS_LIMIT
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return {
|
|
135
|
-
allow: true,
|
|
136
|
-
message: `The sport ${marketLeague} does not have result constraint`,
|
|
137
|
-
};
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export const fetchResultInCurrentSet = (currentSet: number, opticOddsScoresApiResponse: ScoresObject) => {
|
|
141
|
-
let currentHomeGameScore = 0;
|
|
142
|
-
let currentAwayGameScore = 0;
|
|
143
|
-
switch (currentSet) {
|
|
144
|
-
case 1:
|
|
145
|
-
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod1);
|
|
146
|
-
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod1);
|
|
147
|
-
break;
|
|
148
|
-
case 2:
|
|
149
|
-
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod2);
|
|
150
|
-
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod2);
|
|
151
|
-
break;
|
|
152
|
-
case 3:
|
|
153
|
-
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod3);
|
|
154
|
-
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod3);
|
|
155
|
-
break;
|
|
156
|
-
case 4:
|
|
157
|
-
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod4);
|
|
158
|
-
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod4);
|
|
159
|
-
break;
|
|
160
|
-
case 5:
|
|
161
|
-
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod5);
|
|
162
|
-
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod5);
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
return { home: currentHomeGameScore, away: currentAwayGameScore };
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
const checkResultConstraint = (
|
|
169
|
-
homeTeam: string,
|
|
170
|
-
awayTeam: string,
|
|
171
|
-
currentResultInSet: { home: number; away: number },
|
|
172
|
-
currentSetsWon: { home: number; away: number },
|
|
173
|
-
setThreshold: number,
|
|
174
|
-
resultLimit: number
|
|
175
|
-
) => {
|
|
176
|
-
if (Number(currentSetsWon.home) == setThreshold || Number(currentSetsWon.away) == setThreshold) {
|
|
177
|
-
if (Number(currentSetsWon.home) == setThreshold && currentResultInSet.home >= resultLimit) {
|
|
178
|
-
return {
|
|
179
|
-
allow: false,
|
|
180
|
-
message: `Blocking game ${homeTeam} - ${awayTeam} due to current result: ${currentSetsWon.home} - ${currentSetsWon.away} (${currentResultInSet.home} - ${currentResultInSet.away})`,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (Number(currentSetsWon.away) == setThreshold && currentResultInSet.away >= resultLimit) {
|
|
185
|
-
return {
|
|
186
|
-
allow: false,
|
|
187
|
-
message: `Blocking game ${homeTeam} - ${awayTeam} due to current result: ${currentSetsWon.home} - ${currentSetsWon.away} (${currentResultInSet.home} - ${currentResultInSet.away})`,
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
return {
|
|
191
|
-
allow: true,
|
|
192
|
-
message: '',
|
|
193
|
-
currentHomeGameScore: currentResultInSet.home,
|
|
194
|
-
currentAwayGameScore: currentResultInSet.away,
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
allow: true,
|
|
199
|
-
message: '',
|
|
200
|
-
currentHomeGameScore: currentResultInSet.home,
|
|
201
|
-
currentAwayGameScore: currentResultInSet.away,
|
|
202
|
-
};
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const VOLLEYBALL_SET_THRESHOLD = 2;
|
|
206
|
-
const VOLLEYBALL_POINTS_LIMIT = 20;
|
|
207
|
-
const VOLLEYBALL_FIFTH_SET_POINTS_LIMIT = 10;
|
|
208
|
-
const TENNIS_ATP_GRAND_SLAM_SET_THRESHOLD = 2;
|
|
209
|
-
const TENNIS_MASTERS_SET_THRESHOLD = 1;
|
|
210
|
-
const TENNIS_GEMS_LIMIT = 5;
|
|
1
|
+
import { League, Sport, getLeagueSport } from 'overtime-utils';
|
|
2
|
+
import { ScoresObject } from '../types/odds';
|
|
3
|
+
|
|
4
|
+
export const checkGameContraints = (
|
|
5
|
+
opticOddsScoresApiResponse: ScoresObject,
|
|
6
|
+
marketLeague: League,
|
|
7
|
+
constraintsMap: Map<Sport, number>
|
|
8
|
+
) => {
|
|
9
|
+
const marketSport = getLeagueSport(marketLeague);
|
|
10
|
+
const homeTeam = opticOddsScoresApiResponse.homeTeam;
|
|
11
|
+
const awayTeam = opticOddsScoresApiResponse.awayTeam;
|
|
12
|
+
|
|
13
|
+
const currentClock = opticOddsScoresApiResponse.clock;
|
|
14
|
+
const currentPeriod = opticOddsScoresApiResponse.period;
|
|
15
|
+
const currentGameStatus = opticOddsScoresApiResponse.status;
|
|
16
|
+
|
|
17
|
+
if (currentGameStatus.toLowerCase() == 'completed') {
|
|
18
|
+
return {
|
|
19
|
+
allow: false,
|
|
20
|
+
message: `Blocking game ${homeTeam} - ${awayTeam} because it is no longer live.`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (marketSport === Sport.SOCCER) {
|
|
25
|
+
return allowSoccerGame(homeTeam, awayTeam, currentClock, currentPeriod, constraintsMap.get(Sport.SOCCER));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
allow: true,
|
|
30
|
+
message: `The sport ${marketLeague} does not have constraint`,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const allowGameSportWithPeriodConstraint = (
|
|
35
|
+
homeTeam: string,
|
|
36
|
+
awayTeam: string,
|
|
37
|
+
currentPeriod: number,
|
|
38
|
+
periodLimitForLiveTrade: number
|
|
39
|
+
) => {
|
|
40
|
+
if (!Number.isNaN(currentPeriod) && currentPeriod >= periodLimitForLiveTrade) {
|
|
41
|
+
return {
|
|
42
|
+
allow: false,
|
|
43
|
+
message: `Blocking game ${homeTeam} - ${awayTeam} due to period: ${currentPeriod}. period`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { allow: true, message: '' };
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const allowSoccerGame = (
|
|
50
|
+
homeTeam: string,
|
|
51
|
+
awayTeam: string,
|
|
52
|
+
currentClock: string,
|
|
53
|
+
currentPeriod: string,
|
|
54
|
+
soccerMinuteLimitForLiveTrading: number | undefined
|
|
55
|
+
) => {
|
|
56
|
+
const currentClockNumber = Number(currentClock);
|
|
57
|
+
if (
|
|
58
|
+
(!Number.isNaN(currentClockNumber) &&
|
|
59
|
+
soccerMinuteLimitForLiveTrading !== undefined &&
|
|
60
|
+
currentClockNumber >= soccerMinuteLimitForLiveTrading) ||
|
|
61
|
+
(Number.isNaN(currentClockNumber) && currentPeriod.toLowerCase() != 'half')
|
|
62
|
+
) {
|
|
63
|
+
return { allow: false, message: `Blocking game ${homeTeam} - ${awayTeam} due to clock: ${currentClock}min` };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return { allow: true, message: '' };
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const allowGameSportWithResultConstraint = (
|
|
70
|
+
opticOddsScoresApiResponse: ScoresObject,
|
|
71
|
+
homeTeam: string,
|
|
72
|
+
awayTeam: string,
|
|
73
|
+
currentPeriod: string,
|
|
74
|
+
currentScoreHome: number,
|
|
75
|
+
currentScoreAway: number,
|
|
76
|
+
marketLeague: League,
|
|
77
|
+
marketSport: Sport
|
|
78
|
+
) => {
|
|
79
|
+
const setInProgress = Number(currentPeriod);
|
|
80
|
+
const currentResultInSet = fetchResultInCurrentSet(setInProgress, opticOddsScoresApiResponse);
|
|
81
|
+
const atpGrandSlamMatch = opticOddsScoresApiResponse.league.toLowerCase() == 'atp';
|
|
82
|
+
const currentSetsScore = { home: currentScoreHome, away: currentScoreAway };
|
|
83
|
+
|
|
84
|
+
if (marketSport == Sport.VOLLEYBALL) {
|
|
85
|
+
if (setInProgress == 5) {
|
|
86
|
+
return checkResultConstraint(
|
|
87
|
+
homeTeam,
|
|
88
|
+
awayTeam,
|
|
89
|
+
currentResultInSet,
|
|
90
|
+
currentSetsScore,
|
|
91
|
+
VOLLEYBALL_SET_THRESHOLD,
|
|
92
|
+
VOLLEYBALL_FIFTH_SET_POINTS_LIMIT
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
return checkResultConstraint(
|
|
96
|
+
homeTeam,
|
|
97
|
+
awayTeam,
|
|
98
|
+
currentResultInSet,
|
|
99
|
+
currentSetsScore,
|
|
100
|
+
VOLLEYBALL_SET_THRESHOLD,
|
|
101
|
+
VOLLEYBALL_POINTS_LIMIT
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (marketLeague.toString().startsWith(League.TENNIS_GS.toString()) && atpGrandSlamMatch) {
|
|
107
|
+
return checkResultConstraint(
|
|
108
|
+
homeTeam,
|
|
109
|
+
awayTeam,
|
|
110
|
+
currentResultInSet,
|
|
111
|
+
currentSetsScore,
|
|
112
|
+
TENNIS_ATP_GRAND_SLAM_SET_THRESHOLD,
|
|
113
|
+
TENNIS_GEMS_LIMIT
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (
|
|
118
|
+
(marketLeague.toString().startsWith(League.TENNIS_GS.toString()) && !atpGrandSlamMatch) ||
|
|
119
|
+
marketLeague.toString().startsWith(League.TENNIS_MASTERS.toString()) ||
|
|
120
|
+
marketLeague.toString().startsWith(League.SUMMER_OLYMPICS_TENNIS.toString()) ||
|
|
121
|
+
marketLeague.toString().startsWith(League.TENNIS_WTA.toString()) ||
|
|
122
|
+
marketLeague.toString().startsWith(League.TENNIS_ATP_CHALLENGER.toString())
|
|
123
|
+
) {
|
|
124
|
+
return checkResultConstraint(
|
|
125
|
+
homeTeam,
|
|
126
|
+
awayTeam,
|
|
127
|
+
currentResultInSet,
|
|
128
|
+
currentSetsScore,
|
|
129
|
+
TENNIS_MASTERS_SET_THRESHOLD,
|
|
130
|
+
TENNIS_GEMS_LIMIT
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
allow: true,
|
|
136
|
+
message: `The sport ${marketLeague} does not have result constraint`,
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const fetchResultInCurrentSet = (currentSet: number, opticOddsScoresApiResponse: ScoresObject) => {
|
|
141
|
+
let currentHomeGameScore = 0;
|
|
142
|
+
let currentAwayGameScore = 0;
|
|
143
|
+
switch (currentSet) {
|
|
144
|
+
case 1:
|
|
145
|
+
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod1);
|
|
146
|
+
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod1);
|
|
147
|
+
break;
|
|
148
|
+
case 2:
|
|
149
|
+
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod2);
|
|
150
|
+
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod2);
|
|
151
|
+
break;
|
|
152
|
+
case 3:
|
|
153
|
+
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod3);
|
|
154
|
+
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod3);
|
|
155
|
+
break;
|
|
156
|
+
case 4:
|
|
157
|
+
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod4);
|
|
158
|
+
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod4);
|
|
159
|
+
break;
|
|
160
|
+
case 5:
|
|
161
|
+
currentHomeGameScore = Number(opticOddsScoresApiResponse.homePeriod5);
|
|
162
|
+
currentAwayGameScore = Number(opticOddsScoresApiResponse.awayPeriod5);
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
return { home: currentHomeGameScore, away: currentAwayGameScore };
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const checkResultConstraint = (
|
|
169
|
+
homeTeam: string,
|
|
170
|
+
awayTeam: string,
|
|
171
|
+
currentResultInSet: { home: number; away: number },
|
|
172
|
+
currentSetsWon: { home: number; away: number },
|
|
173
|
+
setThreshold: number,
|
|
174
|
+
resultLimit: number
|
|
175
|
+
) => {
|
|
176
|
+
if (Number(currentSetsWon.home) == setThreshold || Number(currentSetsWon.away) == setThreshold) {
|
|
177
|
+
if (Number(currentSetsWon.home) == setThreshold && currentResultInSet.home >= resultLimit) {
|
|
178
|
+
return {
|
|
179
|
+
allow: false,
|
|
180
|
+
message: `Blocking game ${homeTeam} - ${awayTeam} due to current result: ${currentSetsWon.home} - ${currentSetsWon.away} (${currentResultInSet.home} - ${currentResultInSet.away})`,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (Number(currentSetsWon.away) == setThreshold && currentResultInSet.away >= resultLimit) {
|
|
185
|
+
return {
|
|
186
|
+
allow: false,
|
|
187
|
+
message: `Blocking game ${homeTeam} - ${awayTeam} due to current result: ${currentSetsWon.home} - ${currentSetsWon.away} (${currentResultInSet.home} - ${currentResultInSet.away})`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
allow: true,
|
|
192
|
+
message: '',
|
|
193
|
+
currentHomeGameScore: currentResultInSet.home,
|
|
194
|
+
currentAwayGameScore: currentResultInSet.away,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
allow: true,
|
|
199
|
+
message: '',
|
|
200
|
+
currentHomeGameScore: currentResultInSet.home,
|
|
201
|
+
currentAwayGameScore: currentResultInSet.away,
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const VOLLEYBALL_SET_THRESHOLD = 2;
|
|
206
|
+
const VOLLEYBALL_POINTS_LIMIT = 20;
|
|
207
|
+
const VOLLEYBALL_FIFTH_SET_POINTS_LIMIT = 10;
|
|
208
|
+
const TENNIS_ATP_GRAND_SLAM_SET_THRESHOLD = 2;
|
|
209
|
+
const TENNIS_MASTERS_SET_THRESHOLD = 1;
|
|
210
|
+
const TENNIS_GEMS_LIMIT = 5;
|
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
import { LEAGUES_NO_FORMAL_HOME_AWAY } from '../constants/sports';
|
|
2
|
-
|
|
3
|
-
export const teamNamesMatching = (
|
|
4
|
-
leagueId: number,
|
|
5
|
-
marketHomeTeam: string,
|
|
6
|
-
marketAwayTeam: string,
|
|
7
|
-
apiHomeTeam: string,
|
|
8
|
-
apiAwayTeam: string,
|
|
9
|
-
teamsMap: Map<string, string>
|
|
10
|
-
) => {
|
|
11
|
-
let homeTeamsMatch;
|
|
12
|
-
let awayTeamsMatch;
|
|
13
|
-
|
|
14
|
-
if (LEAGUES_NO_FORMAL_HOME_AWAY.includes(leagueId)) {
|
|
15
|
-
homeTeamsMatch =
|
|
16
|
-
apiHomeTeam.toLowerCase() == marketHomeTeam.toLowerCase() ||
|
|
17
|
-
apiHomeTeam.toLowerCase() == marketAwayTeam.toLowerCase();
|
|
18
|
-
awayTeamsMatch =
|
|
19
|
-
apiAwayTeam.toLowerCase() == marketHomeTeam.toLowerCase() ||
|
|
20
|
-
apiAwayTeam.toLowerCase() == marketAwayTeam.toLowerCase();
|
|
21
|
-
} else {
|
|
22
|
-
homeTeamsMatch = apiHomeTeam.toLowerCase() == marketHomeTeam.toLowerCase();
|
|
23
|
-
awayTeamsMatch = apiAwayTeam.toLowerCase() == marketAwayTeam.toLowerCase();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (homeTeamsMatch !== true) {
|
|
27
|
-
const homeTeamOpticOdds = teamsMap.get(apiHomeTeam.toLowerCase());
|
|
28
|
-
const gameHomeTeam = teamsMap.get(marketHomeTeam.toLowerCase());
|
|
29
|
-
const gameAwayTeam = teamsMap.get(marketAwayTeam.toLowerCase());
|
|
30
|
-
const hasUndefinedName = [homeTeamOpticOdds, gameHomeTeam].some((name) => name == undefined);
|
|
31
|
-
|
|
32
|
-
if (hasUndefinedName) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (LEAGUES_NO_FORMAL_HOME_AWAY.includes(leagueId)) {
|
|
37
|
-
homeTeamsMatch = homeTeamOpticOdds == gameHomeTeam || homeTeamOpticOdds == gameAwayTeam;
|
|
38
|
-
} else {
|
|
39
|
-
homeTeamsMatch = homeTeamOpticOdds == gameHomeTeam;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (awayTeamsMatch !== true) {
|
|
44
|
-
const awayTeamOpticOdds = teamsMap.get(apiAwayTeam.toLowerCase());
|
|
45
|
-
const gameHomeTeam = teamsMap.get(marketHomeTeam.toLowerCase());
|
|
46
|
-
const gameAwayTeam = teamsMap.get(marketAwayTeam.toLowerCase());
|
|
47
|
-
|
|
48
|
-
const hasUndefinedName = [awayTeamOpticOdds, gameAwayTeam].some((name) => name == undefined);
|
|
49
|
-
|
|
50
|
-
if (hasUndefinedName) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (LEAGUES_NO_FORMAL_HOME_AWAY.includes(leagueId)) {
|
|
55
|
-
awayTeamsMatch = awayTeamOpticOdds == gameHomeTeam || awayTeamOpticOdds == gameAwayTeam;
|
|
56
|
-
} else {
|
|
57
|
-
awayTeamsMatch = awayTeamOpticOdds == gameAwayTeam;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return homeTeamsMatch && awayTeamsMatch;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const gamesDatesMatching = (
|
|
65
|
-
marketMaturityDate: Date,
|
|
66
|
-
apiStartDate: Date,
|
|
67
|
-
sportId: number,
|
|
68
|
-
timeDifferenceMinutes: number
|
|
69
|
-
) => {
|
|
70
|
-
let datesMatch = false;
|
|
71
|
-
sportId; // TODO: remove it from callers
|
|
72
|
-
|
|
73
|
-
const opticOddsTimestamp = apiStartDate.getTime();
|
|
74
|
-
const marketTimestamp = marketMaturityDate.getTime();
|
|
75
|
-
const differenceBetweenDates = Math.abs(marketTimestamp - opticOddsTimestamp);
|
|
76
|
-
if (differenceBetweenDates <= Number(timeDifferenceMinutes * 60 * 1000)) {
|
|
77
|
-
datesMatch = true;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return datesMatch;
|
|
81
|
-
};
|
|
1
|
+
import { LEAGUES_NO_FORMAL_HOME_AWAY } from '../constants/sports';
|
|
2
|
+
|
|
3
|
+
export const teamNamesMatching = (
|
|
4
|
+
leagueId: number,
|
|
5
|
+
marketHomeTeam: string,
|
|
6
|
+
marketAwayTeam: string,
|
|
7
|
+
apiHomeTeam: string,
|
|
8
|
+
apiAwayTeam: string,
|
|
9
|
+
teamsMap: Map<string, string>
|
|
10
|
+
) => {
|
|
11
|
+
let homeTeamsMatch;
|
|
12
|
+
let awayTeamsMatch;
|
|
13
|
+
|
|
14
|
+
if (LEAGUES_NO_FORMAL_HOME_AWAY.includes(leagueId)) {
|
|
15
|
+
homeTeamsMatch =
|
|
16
|
+
apiHomeTeam.toLowerCase() == marketHomeTeam.toLowerCase() ||
|
|
17
|
+
apiHomeTeam.toLowerCase() == marketAwayTeam.toLowerCase();
|
|
18
|
+
awayTeamsMatch =
|
|
19
|
+
apiAwayTeam.toLowerCase() == marketHomeTeam.toLowerCase() ||
|
|
20
|
+
apiAwayTeam.toLowerCase() == marketAwayTeam.toLowerCase();
|
|
21
|
+
} else {
|
|
22
|
+
homeTeamsMatch = apiHomeTeam.toLowerCase() == marketHomeTeam.toLowerCase();
|
|
23
|
+
awayTeamsMatch = apiAwayTeam.toLowerCase() == marketAwayTeam.toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (homeTeamsMatch !== true) {
|
|
27
|
+
const homeTeamOpticOdds = teamsMap.get(apiHomeTeam.toLowerCase());
|
|
28
|
+
const gameHomeTeam = teamsMap.get(marketHomeTeam.toLowerCase());
|
|
29
|
+
const gameAwayTeam = teamsMap.get(marketAwayTeam.toLowerCase());
|
|
30
|
+
const hasUndefinedName = [homeTeamOpticOdds, gameHomeTeam].some((name) => name == undefined);
|
|
31
|
+
|
|
32
|
+
if (hasUndefinedName) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (LEAGUES_NO_FORMAL_HOME_AWAY.includes(leagueId)) {
|
|
37
|
+
homeTeamsMatch = homeTeamOpticOdds == gameHomeTeam || homeTeamOpticOdds == gameAwayTeam;
|
|
38
|
+
} else {
|
|
39
|
+
homeTeamsMatch = homeTeamOpticOdds == gameHomeTeam;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (awayTeamsMatch !== true) {
|
|
44
|
+
const awayTeamOpticOdds = teamsMap.get(apiAwayTeam.toLowerCase());
|
|
45
|
+
const gameHomeTeam = teamsMap.get(marketHomeTeam.toLowerCase());
|
|
46
|
+
const gameAwayTeam = teamsMap.get(marketAwayTeam.toLowerCase());
|
|
47
|
+
|
|
48
|
+
const hasUndefinedName = [awayTeamOpticOdds, gameAwayTeam].some((name) => name == undefined);
|
|
49
|
+
|
|
50
|
+
if (hasUndefinedName) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (LEAGUES_NO_FORMAL_HOME_AWAY.includes(leagueId)) {
|
|
55
|
+
awayTeamsMatch = awayTeamOpticOdds == gameHomeTeam || awayTeamOpticOdds == gameAwayTeam;
|
|
56
|
+
} else {
|
|
57
|
+
awayTeamsMatch = awayTeamOpticOdds == gameAwayTeam;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return homeTeamsMatch && awayTeamsMatch;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const gamesDatesMatching = (
|
|
65
|
+
marketMaturityDate: Date,
|
|
66
|
+
apiStartDate: Date,
|
|
67
|
+
sportId: number,
|
|
68
|
+
timeDifferenceMinutes: number
|
|
69
|
+
) => {
|
|
70
|
+
let datesMatch = false;
|
|
71
|
+
sportId; // TODO: remove it from callers
|
|
72
|
+
|
|
73
|
+
const opticOddsTimestamp = apiStartDate.getTime();
|
|
74
|
+
const marketTimestamp = marketMaturityDate.getTime();
|
|
75
|
+
const differenceBetweenDates = Math.abs(marketTimestamp - opticOddsTimestamp);
|
|
76
|
+
if (differenceBetweenDates <= Number(timeDifferenceMinutes * 60 * 1000)) {
|
|
77
|
+
datesMatch = true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return datesMatch;
|
|
81
|
+
};
|