Platforms.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import { fork } from "child_process";
  2. import Store from "../state/store.js";
  3. import ProcessData from "../libs/processData.js";
  4. import Logs from "../libs/logs.js";
  5. import { getSolutionsWithRelations } from "../libs/getSolutions.js";
  6. import { updateSolutions } from "./Partner.js";
  7. // import { getPlatformIorInfo } from "./Markets.js";
  8. const getChildOptions = (inspect=9230) => {
  9. return process.env.NODE_ENV == 'development' ? {
  10. execArgv: [`--inspect=${inspect}`],
  11. stdio: ['pipe', 'pipe', 'pipe', 'ipc']
  12. } : {
  13. stdio: ['pipe', 'pipe', 'pipe', 'ipc']
  14. };
  15. }
  16. const triangleProcess = fork("triangle/main.js", [], getChildOptions(9229));
  17. const triangleData = new ProcessData(triangleProcess, 'triangle');
  18. triangleData.registerResponse('gamesRelations', async () => {
  19. const gamesRelations = Object.values(Store.get('gamesRelations') ?? {});
  20. const polymarketOdds = Store.get('polymarket', 'odds') ?? {};
  21. const pinnacleOdds = Store.get('pinnacle', 'odds') ?? {};
  22. const expireTime = Date.now() - 1000 * 15;
  23. const { games: polymarketGames = [], timestamp: polymarketTimestamp = 0 } = polymarketOdds;
  24. const { games: pinnacleGames = [], timestamp: pinnacleTimestamp = 0 } = pinnacleOdds;
  25. const polymarketOddsMap = polymarketTimestamp > expireTime ? new Map(polymarketGames.map(item => [item.id, item])) : new Map();
  26. const pinnacleOddsMap = pinnacleTimestamp > expireTime ? new Map(pinnacleGames.map(item => [item.id, item])) : new Map();
  27. const newRelations = gamesRelations.map(relation => {
  28. const { platforms: { polymarket, pinnacle }, ...rest } = relation;
  29. const polymarketId = polymarket.id;
  30. const pinnacleId = pinnacle.id;
  31. const polymarketOdds = polymarketOddsMap.get(polymarketId)?.odds;
  32. const pinnacleOdds = pinnacleOddsMap.get(pinnacleId)?.odds;
  33. return { ...rest, platforms: {
  34. polymarket: { ...polymarket, odds: polymarketOdds, evtime: polymarketTimestamp },
  35. pinnacle: { ...pinnacle, odds: pinnacleOdds, evtime: pinnacleTimestamp },
  36. }};
  37. });
  38. return Promise.resolve(newRelations);
  39. });
  40. triangleData.registerRequest('solutions', solutions => {
  41. const oldSolutions = new Map((Store.get('solutions') ?? []).map(item => [item.sid, item]));
  42. const newSolutions = new Map(solutions.map(item => [item.sid, item]));
  43. const changed = {
  44. add: [],
  45. update: [],
  46. remove: [],
  47. }
  48. oldSolutions.forEach((item, sid) => {
  49. if (!newSolutions.has(sid)) {
  50. changed.remove.push(sid);
  51. }
  52. else if (newSolutions.get(sid).sol.win_profit_rate != item.sol.win_profit_rate || JSON.stringify(newSolutions.get(sid).cpr) != JSON.stringify(item.cpr)) {
  53. changed.update.push(sid);
  54. }
  55. });
  56. newSolutions.forEach((item, sid) => {
  57. if (!oldSolutions.has(sid)) {
  58. changed.add.push(sid);
  59. }
  60. });
  61. if (changed.update.length || changed.add.length || changed.remove.length) {
  62. Store.set('solutions', solutions);
  63. const gamesRelations = Store.get('gamesRelations') ?? {};
  64. getSolutionsWithRelations(solutions, gamesRelations, 5)
  65. .then(solutionsList => {
  66. Logs.out('solutions with relations', solutionsList);
  67. updateSolutions(solutionsList)
  68. .then(res => {
  69. Logs.out('updateSolutions res', res);
  70. })
  71. .catch(error => {
  72. Logs.err('updateSolutions error', error);
  73. });
  74. })
  75. .catch(error => {
  76. Logs.err('getSolutionsWithRelations error', error);
  77. });
  78. }
  79. });
  80. /**
  81. * 通用的平台数据更新函数
  82. * @param {string} platform - 平台名称
  83. * @param {Array} newItems - 新的数据项数组
  84. * @param {string} storeKey - Store 中的键名
  85. * @returns {Promise}
  86. */
  87. const updatePlatformData = async ({ platform, newItems, storeKey }) => {
  88. if (!platform || !newItems?.length) {
  89. return Promise.reject(new Error('invalid request', { cause: 400 }));
  90. }
  91. let changed = false;
  92. const storeData = Store.get(storeKey) ?? {};
  93. const { [platform]: storePlatformItems = [] } = storeData;
  94. const storePlatformItemsMap = new Map(storePlatformItems.map(item => [item.id, item]));
  95. const newPlatformItemsMap = new Map(newItems.map(item => [item.id, item]));
  96. // 删除不存在的项
  97. storePlatformItemsMap.forEach(item => {
  98. if (!newPlatformItemsMap.has(item.id)) {
  99. storePlatformItemsMap.delete(item.id);
  100. changed = true;
  101. }
  102. });
  103. // 添加新的项
  104. newPlatformItemsMap.forEach(item => {
  105. if (!storePlatformItemsMap.has(item.id)) {
  106. storePlatformItemsMap.set(item.id, item);
  107. changed = true;
  108. }
  109. });
  110. // 更新 Store 中的数据
  111. if (changed) {
  112. const updatedPlatformItems = Array.from(storePlatformItemsMap.values());
  113. storeData[platform] = updatedPlatformItems;
  114. Store.set(storeKey, storeData);
  115. }
  116. return Promise.resolve();
  117. };
  118. /**
  119. * 更新联赛数据
  120. * @param {string} platform - 平台名称
  121. * @param {Array} leagues - 联赛数据
  122. * @returns
  123. */
  124. export const updateLeagues = async ({ platform, leagues }) => {
  125. return updatePlatformData({ platform, newItems: leagues, storeKey: 'leagues' });
  126. };
  127. /**
  128. * 获取过滤后的联赛数据
  129. * @param {string} platform - 平台名称
  130. * @returns
  131. */
  132. export const getRelatedLeagues = async (platform) => {
  133. const polymarketLeagues = Store.get('polymarket', 'leagues') ?? [];
  134. const polymarketLeaguesSet = new Set(polymarketLeagues.map(item => item.id));
  135. const leaguesRelations = Store.get('leaguesRelations') ?? {};
  136. const filteredLeagues = Object.values(leaguesRelations).filter(relation => {
  137. return polymarketLeaguesSet.has(relation.platforms.polymarket.id);
  138. }).map(relation => relation.platforms[platform]);
  139. return filteredLeagues;
  140. }
  141. /**
  142. * 更新比赛数据
  143. * @param {string} platform - 平台名称
  144. * @param {Array} games - 比赛数据
  145. * @returns
  146. */
  147. export const updateGames = async ({ platform, games }) => {
  148. return updatePlatformData({ platform, newItems: games, storeKey: 'games' });
  149. };
  150. /**
  151. * 获取过滤后的比赛数据
  152. * @param {string} platform - 平台名称
  153. * @returns
  154. */
  155. export const getRelatedGames = async (platform) => {
  156. const gamesRelations = Store.get('gamesRelations') ?? {};
  157. const filteredGames = Object.values(gamesRelations).map(relation => relation.platforms[platform]);
  158. return filteredGames;
  159. }
  160. /**
  161. * 更新赔率数据
  162. * @param {string} platform - 平台名称
  163. * @param {Array} games - 赔率数据
  164. * @param {number} timestamp - 时间戳
  165. * @returns
  166. */
  167. export const updateOdds = async ({ platform, games, timestamp }) => {
  168. Store.set(platform, { games, timestamp }, 'odds');
  169. return Promise.resolve();
  170. };
  171. export default {
  172. updateLeagues, getRelatedLeagues,
  173. updateGames, getRelatedGames,
  174. updateOdds,
  175. };