|
|
@@ -9,6 +9,9 @@ const TRACKED_IOR_KEYS = [
|
|
|
];
|
|
|
|
|
|
const TRACKED_IOR_SET = new Set(TRACKED_IOR_KEYS);
|
|
|
+const TRACKED_PLATFORMS = ['pc', 'ob'];
|
|
|
+const TRACKED_PLATFORM_SET = new Set(TRACKED_PLATFORMS);
|
|
|
+const DEFAULT_PLATFORM = 'pc';
|
|
|
|
|
|
const ODDS_HISTORY_START_OFFSET = 2 * 60 * 60 * 1000;
|
|
|
const ODDS_HISTORY_END_OFFSET = 3 * 60 * 60 * 1000;
|
|
|
@@ -41,6 +44,71 @@ const OddsHistory = mongoose.model('OddsHistory', oddsHistorySchema);
|
|
|
|
|
|
const isTrackedKey = (key) => TRACKED_IOR_SET.has(key);
|
|
|
|
|
|
+const normalizePlatform = (platform) => {
|
|
|
+ return TRACKED_PLATFORM_SET.has(platform) ? platform : DEFAULT_PLATFORM;
|
|
|
+}
|
|
|
+
|
|
|
+const getMarketKey = (platform, ior) => {
|
|
|
+ return `${normalizePlatform(platform)}:${ior}`;
|
|
|
+}
|
|
|
+
|
|
|
+const parseMarketKey = (key) => {
|
|
|
+ if (isTrackedKey(key)) {
|
|
|
+ return { ior: key, platform: DEFAULT_PLATFORM };
|
|
|
+ }
|
|
|
+ const [platform, ior] = String(key).split(/[:.]/);
|
|
|
+ if (TRACKED_PLATFORM_SET.has(platform) && isTrackedKey(ior)) {
|
|
|
+ return { ior, platform };
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+}
|
|
|
+
|
|
|
+const getMarketEntries = (markets = {}) => {
|
|
|
+ if (markets instanceof Map) {
|
|
|
+ return Array.from(markets.entries());
|
|
|
+ }
|
|
|
+ return Object.entries(markets);
|
|
|
+}
|
|
|
+
|
|
|
+const normalizeMarkets = (markets = {}) => {
|
|
|
+ const normalized = {};
|
|
|
+ getMarketEntries(markets).forEach(([key, points]) => {
|
|
|
+ const parsed = parseMarketKey(key);
|
|
|
+ if (!parsed || !points?.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const marketKey = getMarketKey(parsed.platform, parsed.ior);
|
|
|
+ normalized[marketKey] = [
|
|
|
+ ...(normalized[marketKey] ?? []),
|
|
|
+ ...points,
|
|
|
+ ].sort((a, b) => a.time - b.time);
|
|
|
+ });
|
|
|
+ return normalized;
|
|
|
+}
|
|
|
+
|
|
|
+const migrateLegacyMarkets = (markets) => {
|
|
|
+ getMarketEntries(markets).forEach(([key, points]) => {
|
|
|
+ const parsed = parseMarketKey(key);
|
|
|
+ if (!parsed || !points?.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const marketKey = getMarketKey(parsed.platform, parsed.ior);
|
|
|
+ if (key === marketKey) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!markets.has(marketKey)) {
|
|
|
+ markets.set(marketKey, points);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ markets.set(marketKey, [
|
|
|
+ ...markets.get(marketKey),
|
|
|
+ ...points,
|
|
|
+ ].sort((a, b) => a.time - b.time));
|
|
|
+ }
|
|
|
+ markets.delete(key);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
const isInsideTrackWindow = (eventTime, recordTime = Date.now()) => {
|
|
|
if (!eventTime) {
|
|
|
return false;
|
|
|
@@ -72,10 +140,11 @@ const appendChangedPoint = (markets, key, point, time) => {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-const recordGameOdds = async ({ game, events }) => {
|
|
|
+const recordGameOdds = async ({ game, events, platform = DEFAULT_PLATFORM }) => {
|
|
|
const eventId = +game?.eventId;
|
|
|
const startTime = +game?.timestamp;
|
|
|
const time = Date.now();
|
|
|
+ platform = normalizePlatform(platform);
|
|
|
|
|
|
if (!eventId || !isInsideTrackWindow(startTime, time) || !events) {
|
|
|
return { updated: false };
|
|
|
@@ -88,20 +157,22 @@ const recordGameOdds = async ({ game, events }) => {
|
|
|
|
|
|
const doc = await OddsHistory.findOne({ eventId });
|
|
|
const markets = doc?.markets ?? new Map();
|
|
|
+ migrateLegacyMarkets(markets);
|
|
|
let changed = false;
|
|
|
- const currentKeys = new Set(trackedEntries.map(([key]) => key));
|
|
|
+ const currentKeys = new Set(trackedEntries.map(([key]) => getMarketKey(platform, key)));
|
|
|
|
|
|
trackedEntries.forEach(([key, point]) => {
|
|
|
- if (appendChangedPoint(markets, key, point, time)) {
|
|
|
+ if (appendChangedPoint(markets, getMarketKey(platform, key), point, time)) {
|
|
|
changed = true;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
TRACKED_IOR_KEYS.forEach(key => {
|
|
|
- if (currentKeys.has(key) || !markets.has(key)) {
|
|
|
+ const marketKey = getMarketKey(platform, key);
|
|
|
+ if (currentKeys.has(marketKey) || !markets.has(marketKey)) {
|
|
|
return;
|
|
|
}
|
|
|
- if (appendChangedPoint(markets, key, { value: 0 }, time)) {
|
|
|
+ if (appendChangedPoint(markets, marketKey, { value: 0 }, time)) {
|
|
|
changed = true;
|
|
|
}
|
|
|
});
|
|
|
@@ -137,10 +208,7 @@ const getGameOddsHistory = async (eventId) => {
|
|
|
if (!history) {
|
|
|
return null;
|
|
|
}
|
|
|
- const markets = Object.fromEntries(
|
|
|
- Object.entries(history.markets ?? {})
|
|
|
- .filter(([key, points]) => isTrackedKey(key) && points?.length),
|
|
|
- );
|
|
|
+ const markets = normalizeMarkets(history.markets);
|
|
|
return {
|
|
|
...history,
|
|
|
markets,
|
|
|
@@ -189,8 +257,7 @@ const getOddsHistoryGames = async ({ page = 1, pageSize = 50, status = -1, keywo
|
|
|
teamAwayName: history.teamAwayName,
|
|
|
startTime: history.startTime,
|
|
|
endTime: history.endTime,
|
|
|
- marketCount: Object.entries(history.markets ?? {})
|
|
|
- .filter(([key, points]) => isTrackedKey(key) && points?.length).length,
|
|
|
+ marketCount: Object.keys(normalizeMarkets(history.markets)).length,
|
|
|
updatedAt: history.updatedAt,
|
|
|
}));
|
|
|
|