overtime-utils 0.2.48 → 0.2.50
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/index.ts +3 -0
- package/main.js +1 -1
- package/package.json +21 -21
- package/src/constants/common.ts +79 -0
- package/src/constants/leagues/basketball.ts +478 -478
- package/src/constants/marketTypes.ts +2331 -2331
- package/src/constants/sports.ts +122 -122
- package/src/enums/sports.ts +741 -741
- package/src/types/feedbackCodes.ts +4 -0
- package/src/utils/feedbackCodes.ts +8 -0
- package/src/utils/markets.ts +528 -528
- package/src/utils/outcomes.ts +372 -372
- package/.claude/settings.local.json +0 -12
package/src/utils/markets.ts
CHANGED
|
@@ -1,528 +1,528 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AWAY_TEAM_MARKET_TYPES,
|
|
3
|
-
AWAY_TEAM_TOTAL_MARKET_TYPES,
|
|
4
|
-
BASKETBALL_MARKET_TYPES,
|
|
5
|
-
BOTH_TEAMS_TO_SCORE_MARKET_TYPES,
|
|
6
|
-
CARDS_MARKET_TYPES,
|
|
7
|
-
COMBINED_POSITIONS_MARKET_TYPES,
|
|
8
|
-
CORNERS_MARKET_TYPES,
|
|
9
|
-
CORRECT_SCORE_MARKET_TYPES,
|
|
10
|
-
CRICKET_MARKET_TYPES,
|
|
11
|
-
DARTS_MARKET_TYPES,
|
|
12
|
-
DOUBLE_CHANCE_MARKET_TYPES,
|
|
13
|
-
EIGHTH_PERIOD_MARKET_TYPES,
|
|
14
|
-
ESPORTS_MARKET_TYPES,
|
|
15
|
-
FIFTH_PERIOD_MARKET_TYPES,
|
|
16
|
-
FIRST_FIVE_INNINGS_MARKET_TYPES,
|
|
17
|
-
FIRST_PERIOD_MARKET_TYPES,
|
|
18
|
-
FIRST_PERIOD_MARKET_TYPES2,
|
|
19
|
-
FIRST_SEVEN_INNINGS_MARKET_TYPES,
|
|
20
|
-
FIRST_THREE_INNINGS_MARKET_TYPES,
|
|
21
|
-
FOOTBALL_MARKET_TYPES,
|
|
22
|
-
FOURTH_PERIOD_MARKET_TYPES,
|
|
23
|
-
FUTURES_MARKET_TYPES,
|
|
24
|
-
HALFTIME_FULLTIME_MARKET_TYPES,
|
|
25
|
-
HIGHEST_SCORING_HALF_MARKET_TYPES,
|
|
26
|
-
HOME_TEAM_MARKET_TYPES,
|
|
27
|
-
HOME_TEAM_TOTAL_MARKET_TYPES,
|
|
28
|
-
NINTH_PERIOD_MARKET_TYPES,
|
|
29
|
-
ONE_SIDE_EXTENDED_PLAYER_PROPS_MARKET_TYPES,
|
|
30
|
-
ONE_SIDE_PLAYER_PROPS_MARKET_TYPES,
|
|
31
|
-
OTHER_YES_NO_MARKET_TYPES,
|
|
32
|
-
PERIOD_MARKET_TYPES,
|
|
33
|
-
PLAYER_PROPS_MARKET_TYPES,
|
|
34
|
-
RACE_TO_MARKET_TYPES,
|
|
35
|
-
SCORE_MARKET_TYPES,
|
|
36
|
-
SECOND_PERIOD_MARKET_TYPES,
|
|
37
|
-
SECOND_PERIOD_MARKET_TYPES2,
|
|
38
|
-
SEVENTH_PERIOD_MARKET_TYPES,
|
|
39
|
-
SGP_BUILDER_MARKET_TYPES,
|
|
40
|
-
SGP_NOT_SUPPORTED_MARKET_TYPES,
|
|
41
|
-
SIXTH_PERIOD_MARKET_TYPES,
|
|
42
|
-
SOCCER_METHOD_OF_VICTORY_MARKET_TYPES,
|
|
43
|
-
SOCCER_SPECIFIC_MARKET_TYPES,
|
|
44
|
-
SOCCER_TOTAL_MARKET_TYPES,
|
|
45
|
-
SPREAD_MARKET_TYPES,
|
|
46
|
-
THIRD_PERIOD_MARKET_TYPES,
|
|
47
|
-
TOTAL_EXACT_MARKET_TYPES,
|
|
48
|
-
TOTAL_MARKET_TYPES,
|
|
49
|
-
TOTAL_ODD_EVEN_MARKET_TYPES,
|
|
50
|
-
TWO_WAY_WINNER_MARKET_TYPES,
|
|
51
|
-
UFC_ENDING_METHOD_MARKET_TYPES,
|
|
52
|
-
UFC_METHOD_OF_VICTORY_MARKET_TYPES,
|
|
53
|
-
UFC_SPECIFIC_MARKET_TYPES,
|
|
54
|
-
UFC_WINNING_ROUND_MARKET_TYPES,
|
|
55
|
-
WINNER_MARKET_TYPES,
|
|
56
|
-
YES_NO_PLAYER_PROPS_MARKET_TYPES,
|
|
57
|
-
} from '../constants/marketTypes';
|
|
58
|
-
import { MarketType } from '../enums/marketTypes';
|
|
59
|
-
import { League, Sport } from '../enums/sports';
|
|
60
|
-
import { SgpBlocker, SgpBlockerMarket } from '../types/sgp';
|
|
61
|
-
import { getLeagueSport } from './sports';
|
|
62
|
-
|
|
63
|
-
export const isWinnerMarket = (marketType: MarketType) => WINNER_MARKET_TYPES.includes(marketType);
|
|
64
|
-
|
|
65
|
-
export const isTotalMarket = (marketType: MarketType) => TOTAL_MARKET_TYPES.includes(marketType);
|
|
66
|
-
export const isHomeTeamTotalMarket = (marketType: MarketType) => HOME_TEAM_TOTAL_MARKET_TYPES.includes(marketType);
|
|
67
|
-
export const isAwayTeamTotalMarket = (marketType: MarketType) => AWAY_TEAM_TOTAL_MARKET_TYPES.includes(marketType);
|
|
68
|
-
export const isTotalOddEvenMarket = (marketType: MarketType) => TOTAL_ODD_EVEN_MARKET_TYPES.includes(marketType);
|
|
69
|
-
export const isTotalExactMarket = (marketType: MarketType) => TOTAL_EXACT_MARKET_TYPES.includes(marketType);
|
|
70
|
-
|
|
71
|
-
export const isSpreadMarket = (marketType: MarketType) => SPREAD_MARKET_TYPES.includes(marketType);
|
|
72
|
-
|
|
73
|
-
export const isPlayerPropsMarket = (marketType: MarketType) => PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
74
|
-
|
|
75
|
-
export const isCombinedPositionsMarket = (marketType: MarketType) =>
|
|
76
|
-
COMBINED_POSITIONS_MARKET_TYPES.includes(marketType);
|
|
77
|
-
|
|
78
|
-
export const isHalftimeFulltimeMarket = (marketType: MarketType) => HALFTIME_FULLTIME_MARKET_TYPES.includes(marketType);
|
|
79
|
-
|
|
80
|
-
export const isFuturesMarket = (marketType: MarketType) => FUTURES_MARKET_TYPES.includes(marketType);
|
|
81
|
-
|
|
82
|
-
export const isOneSideMarket = (league: League, marketType: MarketType) =>
|
|
83
|
-
getLeagueSport(league) === Sport.MOTOSPORT ||
|
|
84
|
-
league == League.US_ELECTION ||
|
|
85
|
-
marketType === MarketType.TO_MAKE_FINAL_FOUR;
|
|
86
|
-
|
|
87
|
-
export const isOneSidePlayerPropsMarket = (marketType: MarketType) =>
|
|
88
|
-
ONE_SIDE_PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
89
|
-
|
|
90
|
-
export const isOneSideExtendedPlayerPropsMarket = (marketType: MarketType) =>
|
|
91
|
-
ONE_SIDE_EXTENDED_PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
92
|
-
|
|
93
|
-
export const isYesNoPlayerPropsMarket = (marketType: MarketType) =>
|
|
94
|
-
YES_NO_PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
95
|
-
|
|
96
|
-
export const isBothTeamsToScoreMarket = (marketType: MarketType) =>
|
|
97
|
-
BOTH_TEAMS_TO_SCORE_MARKET_TYPES.includes(marketType);
|
|
98
|
-
|
|
99
|
-
export const isOtherYesNoMarket = (marketType: MarketType) => OTHER_YES_NO_MARKET_TYPES.includes(marketType);
|
|
100
|
-
|
|
101
|
-
export const isDoubleChanceMarket = (marketType: MarketType) => DOUBLE_CHANCE_MARKET_TYPES.includes(marketType);
|
|
102
|
-
|
|
103
|
-
export const isCorrectScoreMarket = (marketType: MarketType) => CORRECT_SCORE_MARKET_TYPES.includes(marketType);
|
|
104
|
-
|
|
105
|
-
export const isDrawAvailableMarket = (marketType: MarketType) =>
|
|
106
|
-
!TWO_WAY_WINNER_MARKET_TYPES.includes(marketType) &&
|
|
107
|
-
(WINNER_MARKET_TYPES.includes(marketType) ||
|
|
108
|
-
SCORE_MARKET_TYPES.includes(marketType) ||
|
|
109
|
-
RACE_TO_MARKET_TYPES.includes(marketType) ||
|
|
110
|
-
HIGHEST_SCORING_HALF_MARKET_TYPES.includes(marketType));
|
|
111
|
-
|
|
112
|
-
export const isPeriodMarket = (marketType: MarketType) => PERIOD_MARKET_TYPES.includes(marketType);
|
|
113
|
-
|
|
114
|
-
export const isPeriod2Market = (marketType: MarketType) => {
|
|
115
|
-
return (
|
|
116
|
-
(marketType >= MarketType.FIRST_PERIOD_WINNER2 && marketType <= MarketType.NINTH_PERIOD_WINNER2) ||
|
|
117
|
-
(marketType >= MarketType.FIRST_PERIOD_TOTAL2 && marketType <= MarketType.NINTH_PERIOD_TOTAL2) ||
|
|
118
|
-
(marketType >= MarketType.FIRST_PERIOD_SPREAD2 && marketType <= MarketType.NINTH_PERIOD_SPREAD2) ||
|
|
119
|
-
(marketType >= MarketType.FIRST_PERIOD_TOTAL2_ODD_EVEN &&
|
|
120
|
-
marketType <= MarketType.NINTH_PERIOD_TOTAL2_ODD_EVEN) ||
|
|
121
|
-
FIRST_PERIOD_MARKET_TYPES2.includes(marketType) ||
|
|
122
|
-
SECOND_PERIOD_MARKET_TYPES2.includes(marketType)
|
|
123
|
-
);
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
export const isHomeTeamMarket = (marketType: MarketType) => HOME_TEAM_MARKET_TYPES.includes(marketType);
|
|
127
|
-
|
|
128
|
-
export const isAwayTeamMarket = (marketType: MarketType) => AWAY_TEAM_MARKET_TYPES.includes(marketType);
|
|
129
|
-
|
|
130
|
-
export const isScoreMarket = (marketType: MarketType) => SCORE_MARKET_TYPES.includes(marketType);
|
|
131
|
-
|
|
132
|
-
export const isRaceToMarket = (marketType: MarketType) => RACE_TO_MARKET_TYPES.includes(marketType);
|
|
133
|
-
|
|
134
|
-
export const isHighestScoringHalfMarket = (marketType: MarketType) =>
|
|
135
|
-
HIGHEST_SCORING_HALF_MARKET_TYPES.includes(marketType);
|
|
136
|
-
|
|
137
|
-
export const isOnlyOverPlayerPropsMarket = (marketType: MarketType, odds: number[]) =>
|
|
138
|
-
isPlayerPropsMarket(marketType) && odds.length === 1;
|
|
139
|
-
|
|
140
|
-
export const isUfcSpecificMarket = (marketType: MarketType) => UFC_SPECIFIC_MARKET_TYPES.includes(marketType);
|
|
141
|
-
export const isUfcWinningMarket = (marketType: MarketType) => UFC_WINNING_ROUND_MARKET_TYPES.includes(marketType);
|
|
142
|
-
export const isEndingUfcMarket = (marketType: MarketType) => UFC_ENDING_METHOD_MARKET_TYPES.includes(marketType);
|
|
143
|
-
export const isUfcVictoryMarket = (marketType: MarketType) => UFC_METHOD_OF_VICTORY_MARKET_TYPES.includes(marketType);
|
|
144
|
-
|
|
145
|
-
export const isSoccerSpecificMarket = (marketType: MarketType) => SOCCER_SPECIFIC_MARKET_TYPES.includes(marketType);
|
|
146
|
-
export const isSoccerMethodOfVictoryMarket = (marketType: MarketType) => SOCCER_METHOD_OF_VICTORY_MARKET_TYPES.includes(marketType);
|
|
147
|
-
|
|
148
|
-
export const isContractResultView = (marketType: MarketType) =>
|
|
149
|
-
CORNERS_MARKET_TYPES.includes(marketType) ||
|
|
150
|
-
CARDS_MARKET_TYPES.includes(marketType) ||
|
|
151
|
-
CRICKET_MARKET_TYPES.includes(marketType) ||
|
|
152
|
-
FOOTBALL_MARKET_TYPES.includes(marketType) ||
|
|
153
|
-
DARTS_MARKET_TYPES.includes(marketType) ||
|
|
154
|
-
BASKETBALL_MARKET_TYPES.includes(marketType) ||
|
|
155
|
-
ESPORTS_MARKET_TYPES.includes(marketType) ||
|
|
156
|
-
SOCCER_TOTAL_MARKET_TYPES.includes(marketType);
|
|
157
|
-
|
|
158
|
-
export const isTotalOrSpreadWithWholeLine = (marketType: MarketType, line: number) =>
|
|
159
|
-
(isTotalMarket(marketType) || isSpreadMarket(marketType)) && line % 1 === 0;
|
|
160
|
-
|
|
161
|
-
// market: SportMarket
|
|
162
|
-
export const isStalePausedMarket = (market: any, maxDelaySec = 300) =>
|
|
163
|
-
market.isPaused && market.pausedAt && Date.now() - market.pausedAt >= maxDelaySec * 1000;
|
|
164
|
-
|
|
165
|
-
export const isSgpBuilderMarket = (marketType: MarketType) => SGP_BUILDER_MARKET_TYPES.includes(marketType);
|
|
166
|
-
|
|
167
|
-
export const isMarketNotSupportedForSgp = (marketType: MarketType) =>
|
|
168
|
-
SGP_NOT_SUPPORTED_MARKET_TYPES.includes(marketType);
|
|
169
|
-
|
|
170
|
-
/*
|
|
171
|
-
Blocking rules for SGP markets combination:
|
|
172
|
-
|
|
173
|
-
0. Block if markets have same type id and player id, block two markets on the SGP in same direction (both over or both under)
|
|
174
|
-
1. Block halftime-fulltime combining with moneyline
|
|
175
|
-
2. Block same playerId and same typeId for points and PR or PRA combinations
|
|
176
|
-
Block DD and Triple Double on a player with any other prop on that player
|
|
177
|
-
Disalowed props combos (for same playerID > 0):
|
|
178
|
-
- Triple double not allowed with any other prop
|
|
179
|
-
- Double double not allowed with any other prop
|
|
180
|
-
- PRA not allowed with PR, PA and points, rebounds or assist props
|
|
181
|
-
- PR not allowed with points or rebounds
|
|
182
|
-
- PA not allowed with points or assists
|
|
183
|
-
3. Block moneyline and spread on the same team
|
|
184
|
-
Disalowed props for same position (player ID is 0):
|
|
185
|
-
- Moneyline and Spread full time
|
|
186
|
-
- Moneyline and Spread first period
|
|
187
|
-
- Moneyline and Spread second period
|
|
188
|
-
- Moneyline and Spread secondary first period ...
|
|
189
|
-
- Both teams to score on football and over goals per team
|
|
190
|
-
4. Block moneyline with betting on each period individually on the same team
|
|
191
|
-
(e.g. betting on a team to win each period and win moneyline, the first implied the other)
|
|
192
|
-
5. Block over points on each period and over on the whole game
|
|
193
|
-
*/
|
|
194
|
-
|
|
195
|
-
const getBlockers = (sgpBlockers: SgpBlocker[], blockerGroup: number) =>
|
|
196
|
-
sgpBlockers.filter((data) => data.blockerGroup === blockerGroup);
|
|
197
|
-
|
|
198
|
-
const getBlocker = (sgpBlockers: SgpBlocker[], blockerGroup: number, blockerNumber: number) =>
|
|
199
|
-
sgpBlockers.find((data) => data.blockerGroup === blockerGroup && data.blockerNumber === blockerNumber);
|
|
200
|
-
|
|
201
|
-
const getBlockerMessage = (blockerGroup: number, blockerNumber: number) =>
|
|
202
|
-
`Blocker group ${blockerGroup}, #${blockerNumber}`;
|
|
203
|
-
|
|
204
|
-
// Rule #0
|
|
205
|
-
const validateMarketsWithSameDirection = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
206
|
-
const BLOCKER_GROUP = 0;
|
|
207
|
-
|
|
208
|
-
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
209
|
-
|
|
210
|
-
let message = '';
|
|
211
|
-
|
|
212
|
-
if (blockers.length) {
|
|
213
|
-
const blockerNumber = 0;
|
|
214
|
-
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerNumber);
|
|
215
|
-
|
|
216
|
-
if (blocker && blocker.enabled) {
|
|
217
|
-
for (let index = 0; index < markets.length; index++) {
|
|
218
|
-
const market = markets[index];
|
|
219
|
-
|
|
220
|
-
const sport = getLeagueSport(market.leagueId);
|
|
221
|
-
const leagueId = market.leagueId;
|
|
222
|
-
const typeId = market.typeId;
|
|
223
|
-
const playerId = market.playerId;
|
|
224
|
-
const position = market.position;
|
|
225
|
-
|
|
226
|
-
const otherMarkets = markets.filter((_, i) => i !== index && markets[i].gameId === market.gameId);
|
|
227
|
-
const isSameMarketDirection = otherMarkets.some(
|
|
228
|
-
(otherMarket) =>
|
|
229
|
-
(!blocker.sport || blocker.sport === sport) &&
|
|
230
|
-
(!blocker.leagueId || blocker.leagueId === leagueId) &&
|
|
231
|
-
otherMarket.typeId === typeId &&
|
|
232
|
-
otherMarket.playerId === playerId &&
|
|
233
|
-
otherMarket.position === position
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
if (isSameMarketDirection) {
|
|
237
|
-
message =
|
|
238
|
-
getBlocker(sgpBlockers, BLOCKER_GROUP, blockerNumber)?.message ||
|
|
239
|
-
`Blocker group ${BLOCKER_GROUP}, #${blockerNumber}`;
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return message;
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
// Rule #1
|
|
250
|
-
const validateSomeBlockerWithSomeCombined = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
251
|
-
const BLOCKER_GROUP = 1;
|
|
252
|
-
|
|
253
|
-
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
254
|
-
|
|
255
|
-
let message = '';
|
|
256
|
-
|
|
257
|
-
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
258
|
-
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
259
|
-
|
|
260
|
-
if (blocker && blocker.enabled) {
|
|
261
|
-
for (let index = 0; index < markets.length; index++) {
|
|
262
|
-
const market = markets[index];
|
|
263
|
-
const otherMarkets = markets.filter((_, i) => i !== index && markets[i].gameId === market.gameId);
|
|
264
|
-
|
|
265
|
-
const hasSomeBlocker =
|
|
266
|
-
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
267
|
-
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
268
|
-
blocker.blockerTypeIds.includes(market.typeId);
|
|
269
|
-
|
|
270
|
-
if (hasSomeBlocker) {
|
|
271
|
-
const hasSomeCombined = otherMarkets.some(
|
|
272
|
-
(otherMarket) =>
|
|
273
|
-
(!blocker.sport || blocker.sport === getLeagueSport(otherMarket.leagueId)) &&
|
|
274
|
-
(!blocker.leagueId || blocker.leagueId === otherMarket.leagueId) &&
|
|
275
|
-
blocker.combineWithTypeIds.includes(otherMarket.typeId)
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
if (hasSomeCombined) {
|
|
279
|
-
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return message;
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// Rule #2
|
|
291
|
-
const validatePlayerPropsCombinations = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
292
|
-
const BLOCKER_GROUP = 2;
|
|
293
|
-
|
|
294
|
-
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
295
|
-
|
|
296
|
-
let message = '';
|
|
297
|
-
|
|
298
|
-
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
299
|
-
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
300
|
-
|
|
301
|
-
if (blocker && blocker.enabled) {
|
|
302
|
-
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
303
|
-
const market = markets[marketIndex];
|
|
304
|
-
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
305
|
-
|
|
306
|
-
const hasBlockerTypeId =
|
|
307
|
-
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
308
|
-
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
309
|
-
blocker.blockerTypeIds.includes(market.typeId);
|
|
310
|
-
|
|
311
|
-
if (hasBlockerTypeId) {
|
|
312
|
-
const hasCombineWithTypeIds = otherMarkets.some(
|
|
313
|
-
(otherMarket) =>
|
|
314
|
-
(!blocker.combineWithTypeIds.length ||
|
|
315
|
-
blocker.combineWithTypeIds.includes(otherMarket.typeId)) &&
|
|
316
|
-
otherMarket.playerId > 0 &&
|
|
317
|
-
otherMarket.playerId === market.playerId
|
|
318
|
-
);
|
|
319
|
-
if (hasCombineWithTypeIds) {
|
|
320
|
-
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
321
|
-
break;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return message;
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
// Rule #3
|
|
332
|
-
const validateSomeBlockerWithSomeCombinedForSamePosition = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
333
|
-
const BLOCKER_GROUP = 3;
|
|
334
|
-
|
|
335
|
-
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
336
|
-
|
|
337
|
-
let message = '';
|
|
338
|
-
|
|
339
|
-
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
340
|
-
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
341
|
-
|
|
342
|
-
if (blocker && blocker.enabled) {
|
|
343
|
-
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
344
|
-
const market = markets[marketIndex];
|
|
345
|
-
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
346
|
-
|
|
347
|
-
const hasBlockerTypeId =
|
|
348
|
-
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
349
|
-
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
350
|
-
blocker.blockerTypeIds.includes(market.typeId);
|
|
351
|
-
|
|
352
|
-
if (hasBlockerTypeId) {
|
|
353
|
-
const hasCombineWithTypeIds = otherMarkets.some(
|
|
354
|
-
(otherMarket) =>
|
|
355
|
-
blocker.combineWithTypeIds.length &&
|
|
356
|
-
blocker.combineWithTypeIds.includes(otherMarket.typeId) &&
|
|
357
|
-
otherMarket.playerId === 0 &&
|
|
358
|
-
otherMarket.position === market.position
|
|
359
|
-
);
|
|
360
|
-
if (hasCombineWithTypeIds) {
|
|
361
|
-
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
362
|
-
break;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
return message;
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
// Rule #4
|
|
373
|
-
const validateSomeBlockerWithEveryCombinedForSamePosition = (
|
|
374
|
-
markets: SgpBlockerMarket[],
|
|
375
|
-
sgpBlockers: SgpBlocker[]
|
|
376
|
-
) => {
|
|
377
|
-
const BLOCKER_GROUP = 4;
|
|
378
|
-
|
|
379
|
-
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
380
|
-
|
|
381
|
-
let message = '';
|
|
382
|
-
|
|
383
|
-
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
384
|
-
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
385
|
-
|
|
386
|
-
if (blocker && blocker.enabled) {
|
|
387
|
-
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
388
|
-
const market = markets[marketIndex];
|
|
389
|
-
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
390
|
-
|
|
391
|
-
const hasBlockerTypeId =
|
|
392
|
-
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
393
|
-
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
394
|
-
blocker.blockerTypeIds.includes(market.typeId);
|
|
395
|
-
|
|
396
|
-
if (hasBlockerTypeId) {
|
|
397
|
-
const hasCombineWithTypeIds =
|
|
398
|
-
blocker.combineWithTypeIds.length &&
|
|
399
|
-
blocker.combineWithTypeIds.every((combinedTypeId) =>
|
|
400
|
-
otherMarkets.some(
|
|
401
|
-
(otherMarket) =>
|
|
402
|
-
otherMarket.typeId === combinedTypeId &&
|
|
403
|
-
otherMarket.playerId === 0 &&
|
|
404
|
-
otherMarket.position === market.position
|
|
405
|
-
)
|
|
406
|
-
);
|
|
407
|
-
if (hasCombineWithTypeIds) {
|
|
408
|
-
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
409
|
-
break;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
return message;
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
// Rule #5
|
|
420
|
-
const validateSomeBlockerWithEveryCombined = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
421
|
-
const BLOCKER_GROUP = 5;
|
|
422
|
-
|
|
423
|
-
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
424
|
-
|
|
425
|
-
let message = '';
|
|
426
|
-
|
|
427
|
-
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
428
|
-
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
429
|
-
|
|
430
|
-
if (blocker && blocker.enabled) {
|
|
431
|
-
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
432
|
-
const market = markets[marketIndex];
|
|
433
|
-
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
434
|
-
|
|
435
|
-
const hasBlockerTypeId =
|
|
436
|
-
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
437
|
-
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
438
|
-
blocker.blockerTypeIds.includes(market.typeId);
|
|
439
|
-
|
|
440
|
-
if (hasBlockerTypeId) {
|
|
441
|
-
const hasCombineWithTypeIds =
|
|
442
|
-
blocker.combineWithTypeIds.length &&
|
|
443
|
-
blocker.combineWithTypeIds.every((combinedTypeId) =>
|
|
444
|
-
otherMarkets.some(
|
|
445
|
-
(otherMarket) => otherMarket.typeId === combinedTypeId && otherMarket.playerId === 0
|
|
446
|
-
)
|
|
447
|
-
);
|
|
448
|
-
if (hasCombineWithTypeIds) {
|
|
449
|
-
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
450
|
-
break;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
return message;
|
|
458
|
-
};
|
|
459
|
-
|
|
460
|
-
export const getSgpMarketsCombinationAllowed = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
461
|
-
const enabledSgpBlockers = sgpBlockers.filter((sgpBlocker) => sgpBlocker.enabled);
|
|
462
|
-
|
|
463
|
-
const message = enabledSgpBlockers.length
|
|
464
|
-
? validateMarketsWithSameDirection(markets, enabledSgpBlockers) ||
|
|
465
|
-
validateSomeBlockerWithSomeCombined(markets, enabledSgpBlockers) ||
|
|
466
|
-
validatePlayerPropsCombinations(markets, enabledSgpBlockers) ||
|
|
467
|
-
validateSomeBlockerWithSomeCombinedForSamePosition(markets, enabledSgpBlockers) ||
|
|
468
|
-
validateSomeBlockerWithEveryCombinedForSamePosition(markets, enabledSgpBlockers) ||
|
|
469
|
-
validateSomeBlockerWithEveryCombined(markets, enabledSgpBlockers) ||
|
|
470
|
-
''
|
|
471
|
-
: '';
|
|
472
|
-
|
|
473
|
-
return {
|
|
474
|
-
isAllowed: !message,
|
|
475
|
-
message,
|
|
476
|
-
};
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
export const getPeriodsForResultView = (marketType: MarketType, leagueId: League) => {
|
|
480
|
-
if (FIRST_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
481
|
-
return [1];
|
|
482
|
-
}
|
|
483
|
-
if (SECOND_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
484
|
-
return [2];
|
|
485
|
-
}
|
|
486
|
-
if (THIRD_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
487
|
-
return [3];
|
|
488
|
-
}
|
|
489
|
-
if (FOURTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
490
|
-
return [4];
|
|
491
|
-
}
|
|
492
|
-
if (FIFTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
493
|
-
return [5];
|
|
494
|
-
}
|
|
495
|
-
if (SIXTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
496
|
-
return [6];
|
|
497
|
-
}
|
|
498
|
-
if (SEVENTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
499
|
-
return [7];
|
|
500
|
-
}
|
|
501
|
-
if (EIGHTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
502
|
-
return [8];
|
|
503
|
-
}
|
|
504
|
-
if (NINTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
505
|
-
return [9];
|
|
506
|
-
}
|
|
507
|
-
if (FIRST_THREE_INNINGS_MARKET_TYPES.includes(marketType)) {
|
|
508
|
-
return [1, 2, 3];
|
|
509
|
-
}
|
|
510
|
-
if (FIRST_FIVE_INNINGS_MARKET_TYPES.includes(marketType)) {
|
|
511
|
-
return [1, 2, 3, 4, 5];
|
|
512
|
-
}
|
|
513
|
-
if (FIRST_SEVEN_INNINGS_MARKET_TYPES.includes(marketType)) {
|
|
514
|
-
return [1, 2, 3, 4, 5, 6, 7];
|
|
515
|
-
}
|
|
516
|
-
if (FIRST_PERIOD_MARKET_TYPES2.includes(marketType)) {
|
|
517
|
-
const sport = getLeagueSport(leagueId);
|
|
518
|
-
if (sport === Sport.BASEBALL) {
|
|
519
|
-
return [1, 2, 3, 4, 5];
|
|
520
|
-
} else {
|
|
521
|
-
return [1, 2];
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
if (SECOND_PERIOD_MARKET_TYPES2.includes(marketType)) {
|
|
525
|
-
return [3, 4];
|
|
526
|
-
}
|
|
527
|
-
return [];
|
|
528
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
AWAY_TEAM_MARKET_TYPES,
|
|
3
|
+
AWAY_TEAM_TOTAL_MARKET_TYPES,
|
|
4
|
+
BASKETBALL_MARKET_TYPES,
|
|
5
|
+
BOTH_TEAMS_TO_SCORE_MARKET_TYPES,
|
|
6
|
+
CARDS_MARKET_TYPES,
|
|
7
|
+
COMBINED_POSITIONS_MARKET_TYPES,
|
|
8
|
+
CORNERS_MARKET_TYPES,
|
|
9
|
+
CORRECT_SCORE_MARKET_TYPES,
|
|
10
|
+
CRICKET_MARKET_TYPES,
|
|
11
|
+
DARTS_MARKET_TYPES,
|
|
12
|
+
DOUBLE_CHANCE_MARKET_TYPES,
|
|
13
|
+
EIGHTH_PERIOD_MARKET_TYPES,
|
|
14
|
+
ESPORTS_MARKET_TYPES,
|
|
15
|
+
FIFTH_PERIOD_MARKET_TYPES,
|
|
16
|
+
FIRST_FIVE_INNINGS_MARKET_TYPES,
|
|
17
|
+
FIRST_PERIOD_MARKET_TYPES,
|
|
18
|
+
FIRST_PERIOD_MARKET_TYPES2,
|
|
19
|
+
FIRST_SEVEN_INNINGS_MARKET_TYPES,
|
|
20
|
+
FIRST_THREE_INNINGS_MARKET_TYPES,
|
|
21
|
+
FOOTBALL_MARKET_TYPES,
|
|
22
|
+
FOURTH_PERIOD_MARKET_TYPES,
|
|
23
|
+
FUTURES_MARKET_TYPES,
|
|
24
|
+
HALFTIME_FULLTIME_MARKET_TYPES,
|
|
25
|
+
HIGHEST_SCORING_HALF_MARKET_TYPES,
|
|
26
|
+
HOME_TEAM_MARKET_TYPES,
|
|
27
|
+
HOME_TEAM_TOTAL_MARKET_TYPES,
|
|
28
|
+
NINTH_PERIOD_MARKET_TYPES,
|
|
29
|
+
ONE_SIDE_EXTENDED_PLAYER_PROPS_MARKET_TYPES,
|
|
30
|
+
ONE_SIDE_PLAYER_PROPS_MARKET_TYPES,
|
|
31
|
+
OTHER_YES_NO_MARKET_TYPES,
|
|
32
|
+
PERIOD_MARKET_TYPES,
|
|
33
|
+
PLAYER_PROPS_MARKET_TYPES,
|
|
34
|
+
RACE_TO_MARKET_TYPES,
|
|
35
|
+
SCORE_MARKET_TYPES,
|
|
36
|
+
SECOND_PERIOD_MARKET_TYPES,
|
|
37
|
+
SECOND_PERIOD_MARKET_TYPES2,
|
|
38
|
+
SEVENTH_PERIOD_MARKET_TYPES,
|
|
39
|
+
SGP_BUILDER_MARKET_TYPES,
|
|
40
|
+
SGP_NOT_SUPPORTED_MARKET_TYPES,
|
|
41
|
+
SIXTH_PERIOD_MARKET_TYPES,
|
|
42
|
+
SOCCER_METHOD_OF_VICTORY_MARKET_TYPES,
|
|
43
|
+
SOCCER_SPECIFIC_MARKET_TYPES,
|
|
44
|
+
SOCCER_TOTAL_MARKET_TYPES,
|
|
45
|
+
SPREAD_MARKET_TYPES,
|
|
46
|
+
THIRD_PERIOD_MARKET_TYPES,
|
|
47
|
+
TOTAL_EXACT_MARKET_TYPES,
|
|
48
|
+
TOTAL_MARKET_TYPES,
|
|
49
|
+
TOTAL_ODD_EVEN_MARKET_TYPES,
|
|
50
|
+
TWO_WAY_WINNER_MARKET_TYPES,
|
|
51
|
+
UFC_ENDING_METHOD_MARKET_TYPES,
|
|
52
|
+
UFC_METHOD_OF_VICTORY_MARKET_TYPES,
|
|
53
|
+
UFC_SPECIFIC_MARKET_TYPES,
|
|
54
|
+
UFC_WINNING_ROUND_MARKET_TYPES,
|
|
55
|
+
WINNER_MARKET_TYPES,
|
|
56
|
+
YES_NO_PLAYER_PROPS_MARKET_TYPES,
|
|
57
|
+
} from '../constants/marketTypes';
|
|
58
|
+
import { MarketType } from '../enums/marketTypes';
|
|
59
|
+
import { League, Sport } from '../enums/sports';
|
|
60
|
+
import { SgpBlocker, SgpBlockerMarket } from '../types/sgp';
|
|
61
|
+
import { getLeagueSport } from './sports';
|
|
62
|
+
|
|
63
|
+
export const isWinnerMarket = (marketType: MarketType) => WINNER_MARKET_TYPES.includes(marketType);
|
|
64
|
+
|
|
65
|
+
export const isTotalMarket = (marketType: MarketType) => TOTAL_MARKET_TYPES.includes(marketType);
|
|
66
|
+
export const isHomeTeamTotalMarket = (marketType: MarketType) => HOME_TEAM_TOTAL_MARKET_TYPES.includes(marketType);
|
|
67
|
+
export const isAwayTeamTotalMarket = (marketType: MarketType) => AWAY_TEAM_TOTAL_MARKET_TYPES.includes(marketType);
|
|
68
|
+
export const isTotalOddEvenMarket = (marketType: MarketType) => TOTAL_ODD_EVEN_MARKET_TYPES.includes(marketType);
|
|
69
|
+
export const isTotalExactMarket = (marketType: MarketType) => TOTAL_EXACT_MARKET_TYPES.includes(marketType);
|
|
70
|
+
|
|
71
|
+
export const isSpreadMarket = (marketType: MarketType) => SPREAD_MARKET_TYPES.includes(marketType);
|
|
72
|
+
|
|
73
|
+
export const isPlayerPropsMarket = (marketType: MarketType) => PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
74
|
+
|
|
75
|
+
export const isCombinedPositionsMarket = (marketType: MarketType) =>
|
|
76
|
+
COMBINED_POSITIONS_MARKET_TYPES.includes(marketType);
|
|
77
|
+
|
|
78
|
+
export const isHalftimeFulltimeMarket = (marketType: MarketType) => HALFTIME_FULLTIME_MARKET_TYPES.includes(marketType);
|
|
79
|
+
|
|
80
|
+
export const isFuturesMarket = (marketType: MarketType) => FUTURES_MARKET_TYPES.includes(marketType);
|
|
81
|
+
|
|
82
|
+
export const isOneSideMarket = (league: League, marketType: MarketType) =>
|
|
83
|
+
getLeagueSport(league) === Sport.MOTOSPORT ||
|
|
84
|
+
league == League.US_ELECTION ||
|
|
85
|
+
marketType === MarketType.TO_MAKE_FINAL_FOUR;
|
|
86
|
+
|
|
87
|
+
export const isOneSidePlayerPropsMarket = (marketType: MarketType) =>
|
|
88
|
+
ONE_SIDE_PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
89
|
+
|
|
90
|
+
export const isOneSideExtendedPlayerPropsMarket = (marketType: MarketType) =>
|
|
91
|
+
ONE_SIDE_EXTENDED_PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
92
|
+
|
|
93
|
+
export const isYesNoPlayerPropsMarket = (marketType: MarketType) =>
|
|
94
|
+
YES_NO_PLAYER_PROPS_MARKET_TYPES.includes(marketType);
|
|
95
|
+
|
|
96
|
+
export const isBothTeamsToScoreMarket = (marketType: MarketType) =>
|
|
97
|
+
BOTH_TEAMS_TO_SCORE_MARKET_TYPES.includes(marketType);
|
|
98
|
+
|
|
99
|
+
export const isOtherYesNoMarket = (marketType: MarketType) => OTHER_YES_NO_MARKET_TYPES.includes(marketType);
|
|
100
|
+
|
|
101
|
+
export const isDoubleChanceMarket = (marketType: MarketType) => DOUBLE_CHANCE_MARKET_TYPES.includes(marketType);
|
|
102
|
+
|
|
103
|
+
export const isCorrectScoreMarket = (marketType: MarketType) => CORRECT_SCORE_MARKET_TYPES.includes(marketType);
|
|
104
|
+
|
|
105
|
+
export const isDrawAvailableMarket = (marketType: MarketType) =>
|
|
106
|
+
!TWO_WAY_WINNER_MARKET_TYPES.includes(marketType) &&
|
|
107
|
+
(WINNER_MARKET_TYPES.includes(marketType) ||
|
|
108
|
+
SCORE_MARKET_TYPES.includes(marketType) ||
|
|
109
|
+
RACE_TO_MARKET_TYPES.includes(marketType) ||
|
|
110
|
+
HIGHEST_SCORING_HALF_MARKET_TYPES.includes(marketType));
|
|
111
|
+
|
|
112
|
+
export const isPeriodMarket = (marketType: MarketType) => PERIOD_MARKET_TYPES.includes(marketType);
|
|
113
|
+
|
|
114
|
+
export const isPeriod2Market = (marketType: MarketType) => {
|
|
115
|
+
return (
|
|
116
|
+
(marketType >= MarketType.FIRST_PERIOD_WINNER2 && marketType <= MarketType.NINTH_PERIOD_WINNER2) ||
|
|
117
|
+
(marketType >= MarketType.FIRST_PERIOD_TOTAL2 && marketType <= MarketType.NINTH_PERIOD_TOTAL2) ||
|
|
118
|
+
(marketType >= MarketType.FIRST_PERIOD_SPREAD2 && marketType <= MarketType.NINTH_PERIOD_SPREAD2) ||
|
|
119
|
+
(marketType >= MarketType.FIRST_PERIOD_TOTAL2_ODD_EVEN &&
|
|
120
|
+
marketType <= MarketType.NINTH_PERIOD_TOTAL2_ODD_EVEN) ||
|
|
121
|
+
FIRST_PERIOD_MARKET_TYPES2.includes(marketType) ||
|
|
122
|
+
SECOND_PERIOD_MARKET_TYPES2.includes(marketType)
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const isHomeTeamMarket = (marketType: MarketType) => HOME_TEAM_MARKET_TYPES.includes(marketType);
|
|
127
|
+
|
|
128
|
+
export const isAwayTeamMarket = (marketType: MarketType) => AWAY_TEAM_MARKET_TYPES.includes(marketType);
|
|
129
|
+
|
|
130
|
+
export const isScoreMarket = (marketType: MarketType) => SCORE_MARKET_TYPES.includes(marketType);
|
|
131
|
+
|
|
132
|
+
export const isRaceToMarket = (marketType: MarketType) => RACE_TO_MARKET_TYPES.includes(marketType);
|
|
133
|
+
|
|
134
|
+
export const isHighestScoringHalfMarket = (marketType: MarketType) =>
|
|
135
|
+
HIGHEST_SCORING_HALF_MARKET_TYPES.includes(marketType);
|
|
136
|
+
|
|
137
|
+
export const isOnlyOverPlayerPropsMarket = (marketType: MarketType, odds: number[]) =>
|
|
138
|
+
isPlayerPropsMarket(marketType) && odds.length === 1;
|
|
139
|
+
|
|
140
|
+
export const isUfcSpecificMarket = (marketType: MarketType) => UFC_SPECIFIC_MARKET_TYPES.includes(marketType);
|
|
141
|
+
export const isUfcWinningMarket = (marketType: MarketType) => UFC_WINNING_ROUND_MARKET_TYPES.includes(marketType);
|
|
142
|
+
export const isEndingUfcMarket = (marketType: MarketType) => UFC_ENDING_METHOD_MARKET_TYPES.includes(marketType);
|
|
143
|
+
export const isUfcVictoryMarket = (marketType: MarketType) => UFC_METHOD_OF_VICTORY_MARKET_TYPES.includes(marketType);
|
|
144
|
+
|
|
145
|
+
export const isSoccerSpecificMarket = (marketType: MarketType) => SOCCER_SPECIFIC_MARKET_TYPES.includes(marketType);
|
|
146
|
+
export const isSoccerMethodOfVictoryMarket = (marketType: MarketType) => SOCCER_METHOD_OF_VICTORY_MARKET_TYPES.includes(marketType);
|
|
147
|
+
|
|
148
|
+
export const isContractResultView = (marketType: MarketType) =>
|
|
149
|
+
CORNERS_MARKET_TYPES.includes(marketType) ||
|
|
150
|
+
CARDS_MARKET_TYPES.includes(marketType) ||
|
|
151
|
+
CRICKET_MARKET_TYPES.includes(marketType) ||
|
|
152
|
+
FOOTBALL_MARKET_TYPES.includes(marketType) ||
|
|
153
|
+
DARTS_MARKET_TYPES.includes(marketType) ||
|
|
154
|
+
BASKETBALL_MARKET_TYPES.includes(marketType) ||
|
|
155
|
+
ESPORTS_MARKET_TYPES.includes(marketType) ||
|
|
156
|
+
SOCCER_TOTAL_MARKET_TYPES.includes(marketType);
|
|
157
|
+
|
|
158
|
+
export const isTotalOrSpreadWithWholeLine = (marketType: MarketType, line: number) =>
|
|
159
|
+
(isTotalMarket(marketType) || isSpreadMarket(marketType)) && line % 1 === 0;
|
|
160
|
+
|
|
161
|
+
// market: SportMarket
|
|
162
|
+
export const isStalePausedMarket = (market: any, maxDelaySec = 300) =>
|
|
163
|
+
market.isPaused && market.pausedAt && Date.now() - market.pausedAt >= maxDelaySec * 1000;
|
|
164
|
+
|
|
165
|
+
export const isSgpBuilderMarket = (marketType: MarketType) => SGP_BUILDER_MARKET_TYPES.includes(marketType);
|
|
166
|
+
|
|
167
|
+
export const isMarketNotSupportedForSgp = (marketType: MarketType) =>
|
|
168
|
+
SGP_NOT_SUPPORTED_MARKET_TYPES.includes(marketType);
|
|
169
|
+
|
|
170
|
+
/*
|
|
171
|
+
Blocking rules for SGP markets combination:
|
|
172
|
+
|
|
173
|
+
0. Block if markets have same type id and player id, block two markets on the SGP in same direction (both over or both under)
|
|
174
|
+
1. Block halftime-fulltime combining with moneyline
|
|
175
|
+
2. Block same playerId and same typeId for points and PR or PRA combinations
|
|
176
|
+
Block DD and Triple Double on a player with any other prop on that player
|
|
177
|
+
Disalowed props combos (for same playerID > 0):
|
|
178
|
+
- Triple double not allowed with any other prop
|
|
179
|
+
- Double double not allowed with any other prop
|
|
180
|
+
- PRA not allowed with PR, PA and points, rebounds or assist props
|
|
181
|
+
- PR not allowed with points or rebounds
|
|
182
|
+
- PA not allowed with points or assists
|
|
183
|
+
3. Block moneyline and spread on the same team
|
|
184
|
+
Disalowed props for same position (player ID is 0):
|
|
185
|
+
- Moneyline and Spread full time
|
|
186
|
+
- Moneyline and Spread first period
|
|
187
|
+
- Moneyline and Spread second period
|
|
188
|
+
- Moneyline and Spread secondary first period ...
|
|
189
|
+
- Both teams to score on football and over goals per team
|
|
190
|
+
4. Block moneyline with betting on each period individually on the same team
|
|
191
|
+
(e.g. betting on a team to win each period and win moneyline, the first implied the other)
|
|
192
|
+
5. Block over points on each period and over on the whole game
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
const getBlockers = (sgpBlockers: SgpBlocker[], blockerGroup: number) =>
|
|
196
|
+
sgpBlockers.filter((data) => data.blockerGroup === blockerGroup);
|
|
197
|
+
|
|
198
|
+
const getBlocker = (sgpBlockers: SgpBlocker[], blockerGroup: number, blockerNumber: number) =>
|
|
199
|
+
sgpBlockers.find((data) => data.blockerGroup === blockerGroup && data.blockerNumber === blockerNumber);
|
|
200
|
+
|
|
201
|
+
const getBlockerMessage = (blockerGroup: number, blockerNumber: number) =>
|
|
202
|
+
`Blocker group ${blockerGroup}, #${blockerNumber}`;
|
|
203
|
+
|
|
204
|
+
// Rule #0
|
|
205
|
+
const validateMarketsWithSameDirection = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
206
|
+
const BLOCKER_GROUP = 0;
|
|
207
|
+
|
|
208
|
+
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
209
|
+
|
|
210
|
+
let message = '';
|
|
211
|
+
|
|
212
|
+
if (blockers.length) {
|
|
213
|
+
const blockerNumber = 0;
|
|
214
|
+
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerNumber);
|
|
215
|
+
|
|
216
|
+
if (blocker && blocker.enabled) {
|
|
217
|
+
for (let index = 0; index < markets.length; index++) {
|
|
218
|
+
const market = markets[index];
|
|
219
|
+
|
|
220
|
+
const sport = getLeagueSport(market.leagueId);
|
|
221
|
+
const leagueId = market.leagueId;
|
|
222
|
+
const typeId = market.typeId;
|
|
223
|
+
const playerId = market.playerId;
|
|
224
|
+
const position = market.position;
|
|
225
|
+
|
|
226
|
+
const otherMarkets = markets.filter((_, i) => i !== index && markets[i].gameId === market.gameId);
|
|
227
|
+
const isSameMarketDirection = otherMarkets.some(
|
|
228
|
+
(otherMarket) =>
|
|
229
|
+
(!blocker.sport || blocker.sport === sport) &&
|
|
230
|
+
(!blocker.leagueId || blocker.leagueId === leagueId) &&
|
|
231
|
+
otherMarket.typeId === typeId &&
|
|
232
|
+
otherMarket.playerId === playerId &&
|
|
233
|
+
otherMarket.position === position
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
if (isSameMarketDirection) {
|
|
237
|
+
message =
|
|
238
|
+
getBlocker(sgpBlockers, BLOCKER_GROUP, blockerNumber)?.message ||
|
|
239
|
+
`Blocker group ${BLOCKER_GROUP}, #${blockerNumber}`;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return message;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Rule #1
|
|
250
|
+
const validateSomeBlockerWithSomeCombined = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
251
|
+
const BLOCKER_GROUP = 1;
|
|
252
|
+
|
|
253
|
+
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
254
|
+
|
|
255
|
+
let message = '';
|
|
256
|
+
|
|
257
|
+
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
258
|
+
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
259
|
+
|
|
260
|
+
if (blocker && blocker.enabled) {
|
|
261
|
+
for (let index = 0; index < markets.length; index++) {
|
|
262
|
+
const market = markets[index];
|
|
263
|
+
const otherMarkets = markets.filter((_, i) => i !== index && markets[i].gameId === market.gameId);
|
|
264
|
+
|
|
265
|
+
const hasSomeBlocker =
|
|
266
|
+
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
267
|
+
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
268
|
+
blocker.blockerTypeIds.includes(market.typeId);
|
|
269
|
+
|
|
270
|
+
if (hasSomeBlocker) {
|
|
271
|
+
const hasSomeCombined = otherMarkets.some(
|
|
272
|
+
(otherMarket) =>
|
|
273
|
+
(!blocker.sport || blocker.sport === getLeagueSport(otherMarket.leagueId)) &&
|
|
274
|
+
(!blocker.leagueId || blocker.leagueId === otherMarket.leagueId) &&
|
|
275
|
+
blocker.combineWithTypeIds.includes(otherMarket.typeId)
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
if (hasSomeCombined) {
|
|
279
|
+
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return message;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Rule #2
|
|
291
|
+
const validatePlayerPropsCombinations = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
292
|
+
const BLOCKER_GROUP = 2;
|
|
293
|
+
|
|
294
|
+
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
295
|
+
|
|
296
|
+
let message = '';
|
|
297
|
+
|
|
298
|
+
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
299
|
+
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
300
|
+
|
|
301
|
+
if (blocker && blocker.enabled) {
|
|
302
|
+
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
303
|
+
const market = markets[marketIndex];
|
|
304
|
+
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
305
|
+
|
|
306
|
+
const hasBlockerTypeId =
|
|
307
|
+
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
308
|
+
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
309
|
+
blocker.blockerTypeIds.includes(market.typeId);
|
|
310
|
+
|
|
311
|
+
if (hasBlockerTypeId) {
|
|
312
|
+
const hasCombineWithTypeIds = otherMarkets.some(
|
|
313
|
+
(otherMarket) =>
|
|
314
|
+
(!blocker.combineWithTypeIds.length ||
|
|
315
|
+
blocker.combineWithTypeIds.includes(otherMarket.typeId)) &&
|
|
316
|
+
otherMarket.playerId > 0 &&
|
|
317
|
+
otherMarket.playerId === market.playerId
|
|
318
|
+
);
|
|
319
|
+
if (hasCombineWithTypeIds) {
|
|
320
|
+
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return message;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// Rule #3
|
|
332
|
+
const validateSomeBlockerWithSomeCombinedForSamePosition = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
333
|
+
const BLOCKER_GROUP = 3;
|
|
334
|
+
|
|
335
|
+
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
336
|
+
|
|
337
|
+
let message = '';
|
|
338
|
+
|
|
339
|
+
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
340
|
+
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
341
|
+
|
|
342
|
+
if (blocker && blocker.enabled) {
|
|
343
|
+
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
344
|
+
const market = markets[marketIndex];
|
|
345
|
+
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
346
|
+
|
|
347
|
+
const hasBlockerTypeId =
|
|
348
|
+
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
349
|
+
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
350
|
+
blocker.blockerTypeIds.includes(market.typeId);
|
|
351
|
+
|
|
352
|
+
if (hasBlockerTypeId) {
|
|
353
|
+
const hasCombineWithTypeIds = otherMarkets.some(
|
|
354
|
+
(otherMarket) =>
|
|
355
|
+
blocker.combineWithTypeIds.length &&
|
|
356
|
+
blocker.combineWithTypeIds.includes(otherMarket.typeId) &&
|
|
357
|
+
otherMarket.playerId === 0 &&
|
|
358
|
+
otherMarket.position === market.position
|
|
359
|
+
);
|
|
360
|
+
if (hasCombineWithTypeIds) {
|
|
361
|
+
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return message;
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// Rule #4
|
|
373
|
+
const validateSomeBlockerWithEveryCombinedForSamePosition = (
|
|
374
|
+
markets: SgpBlockerMarket[],
|
|
375
|
+
sgpBlockers: SgpBlocker[]
|
|
376
|
+
) => {
|
|
377
|
+
const BLOCKER_GROUP = 4;
|
|
378
|
+
|
|
379
|
+
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
380
|
+
|
|
381
|
+
let message = '';
|
|
382
|
+
|
|
383
|
+
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
384
|
+
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
385
|
+
|
|
386
|
+
if (blocker && blocker.enabled) {
|
|
387
|
+
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
388
|
+
const market = markets[marketIndex];
|
|
389
|
+
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
390
|
+
|
|
391
|
+
const hasBlockerTypeId =
|
|
392
|
+
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
393
|
+
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
394
|
+
blocker.blockerTypeIds.includes(market.typeId);
|
|
395
|
+
|
|
396
|
+
if (hasBlockerTypeId) {
|
|
397
|
+
const hasCombineWithTypeIds =
|
|
398
|
+
blocker.combineWithTypeIds.length &&
|
|
399
|
+
blocker.combineWithTypeIds.every((combinedTypeId) =>
|
|
400
|
+
otherMarkets.some(
|
|
401
|
+
(otherMarket) =>
|
|
402
|
+
otherMarket.typeId === combinedTypeId &&
|
|
403
|
+
otherMarket.playerId === 0 &&
|
|
404
|
+
otherMarket.position === market.position
|
|
405
|
+
)
|
|
406
|
+
);
|
|
407
|
+
if (hasCombineWithTypeIds) {
|
|
408
|
+
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return message;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
// Rule #5
|
|
420
|
+
const validateSomeBlockerWithEveryCombined = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
421
|
+
const BLOCKER_GROUP = 5;
|
|
422
|
+
|
|
423
|
+
const blockers = getBlockers(sgpBlockers, BLOCKER_GROUP);
|
|
424
|
+
|
|
425
|
+
let message = '';
|
|
426
|
+
|
|
427
|
+
for (let blockerIndex = 0; blockerIndex < blockers.length; blockerIndex++) {
|
|
428
|
+
const blocker = getBlocker(blockers, BLOCKER_GROUP, blockerIndex);
|
|
429
|
+
|
|
430
|
+
if (blocker && blocker.enabled) {
|
|
431
|
+
for (let marketIndex = 0; marketIndex < markets.length; marketIndex++) {
|
|
432
|
+
const market = markets[marketIndex];
|
|
433
|
+
const otherMarkets = markets.filter((_, i) => i !== marketIndex && markets[i].gameId === market.gameId);
|
|
434
|
+
|
|
435
|
+
const hasBlockerTypeId =
|
|
436
|
+
(!blocker.sport || blocker.sport === getLeagueSport(market.leagueId)) &&
|
|
437
|
+
(!blocker.leagueId || blocker.leagueId === market.leagueId) &&
|
|
438
|
+
blocker.blockerTypeIds.includes(market.typeId);
|
|
439
|
+
|
|
440
|
+
if (hasBlockerTypeId) {
|
|
441
|
+
const hasCombineWithTypeIds =
|
|
442
|
+
blocker.combineWithTypeIds.length &&
|
|
443
|
+
blocker.combineWithTypeIds.every((combinedTypeId) =>
|
|
444
|
+
otherMarkets.some(
|
|
445
|
+
(otherMarket) => otherMarket.typeId === combinedTypeId && otherMarket.playerId === 0
|
|
446
|
+
)
|
|
447
|
+
);
|
|
448
|
+
if (hasCombineWithTypeIds) {
|
|
449
|
+
message = blocker?.message || getBlockerMessage(BLOCKER_GROUP, blockerIndex);
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return message;
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
export const getSgpMarketsCombinationAllowed = (markets: SgpBlockerMarket[], sgpBlockers: SgpBlocker[]) => {
|
|
461
|
+
const enabledSgpBlockers = sgpBlockers.filter((sgpBlocker) => sgpBlocker.enabled);
|
|
462
|
+
|
|
463
|
+
const message = enabledSgpBlockers.length
|
|
464
|
+
? validateMarketsWithSameDirection(markets, enabledSgpBlockers) ||
|
|
465
|
+
validateSomeBlockerWithSomeCombined(markets, enabledSgpBlockers) ||
|
|
466
|
+
validatePlayerPropsCombinations(markets, enabledSgpBlockers) ||
|
|
467
|
+
validateSomeBlockerWithSomeCombinedForSamePosition(markets, enabledSgpBlockers) ||
|
|
468
|
+
validateSomeBlockerWithEveryCombinedForSamePosition(markets, enabledSgpBlockers) ||
|
|
469
|
+
validateSomeBlockerWithEveryCombined(markets, enabledSgpBlockers) ||
|
|
470
|
+
''
|
|
471
|
+
: '';
|
|
472
|
+
|
|
473
|
+
return {
|
|
474
|
+
isAllowed: !message,
|
|
475
|
+
message,
|
|
476
|
+
};
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
export const getPeriodsForResultView = (marketType: MarketType, leagueId: League) => {
|
|
480
|
+
if (FIRST_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
481
|
+
return [1];
|
|
482
|
+
}
|
|
483
|
+
if (SECOND_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
484
|
+
return [2];
|
|
485
|
+
}
|
|
486
|
+
if (THIRD_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
487
|
+
return [3];
|
|
488
|
+
}
|
|
489
|
+
if (FOURTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
490
|
+
return [4];
|
|
491
|
+
}
|
|
492
|
+
if (FIFTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
493
|
+
return [5];
|
|
494
|
+
}
|
|
495
|
+
if (SIXTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
496
|
+
return [6];
|
|
497
|
+
}
|
|
498
|
+
if (SEVENTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
499
|
+
return [7];
|
|
500
|
+
}
|
|
501
|
+
if (EIGHTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
502
|
+
return [8];
|
|
503
|
+
}
|
|
504
|
+
if (NINTH_PERIOD_MARKET_TYPES.includes(marketType)) {
|
|
505
|
+
return [9];
|
|
506
|
+
}
|
|
507
|
+
if (FIRST_THREE_INNINGS_MARKET_TYPES.includes(marketType)) {
|
|
508
|
+
return [1, 2, 3];
|
|
509
|
+
}
|
|
510
|
+
if (FIRST_FIVE_INNINGS_MARKET_TYPES.includes(marketType)) {
|
|
511
|
+
return [1, 2, 3, 4, 5];
|
|
512
|
+
}
|
|
513
|
+
if (FIRST_SEVEN_INNINGS_MARKET_TYPES.includes(marketType)) {
|
|
514
|
+
return [1, 2, 3, 4, 5, 6, 7];
|
|
515
|
+
}
|
|
516
|
+
if (FIRST_PERIOD_MARKET_TYPES2.includes(marketType)) {
|
|
517
|
+
const sport = getLeagueSport(leagueId);
|
|
518
|
+
if (sport === Sport.BASEBALL) {
|
|
519
|
+
return [1, 2, 3, 4, 5];
|
|
520
|
+
} else {
|
|
521
|
+
return [1, 2];
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (SECOND_PERIOD_MARKET_TYPES2.includes(marketType)) {
|
|
525
|
+
return [3, 4];
|
|
526
|
+
}
|
|
527
|
+
return [];
|
|
528
|
+
};
|