GamesPs.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. const axios = require('axios');
  2. const Logs = require('../libs/logs');
  3. const PS_IOR_KEYS = [
  4. ['0', 'ior_mh', 'ior_mn', 'ior_mc'],
  5. // ['0', 'ior_rh_05', 'ior_mn', 'ior_rc_05'],
  6. ['-1', 'ior_rh_15', 'ior_wmh_1', 'ior_rac_05'],
  7. ['-2', 'ior_rh_25', 'ior_wmh_2', 'ior_rac_15'],
  8. ['+1', 'ior_rah_05', 'ior_wmc_1', 'ior_rc_15'],
  9. ['+2', 'ior_rah_15', 'ior_wmc_2', 'ior_rc_25'],
  10. ];
  11. const BASE_URL = 'https://api.isthe.me/api/p';
  12. const GAMES = {
  13. Leagues: {},
  14. List: {},
  15. Baselist: {}
  16. };
  17. /**
  18. * 精确浮点数字
  19. * @param {number} number
  20. * @param {number} x
  21. * @returns {number}
  22. */
  23. const fixFloat = (number, x=2) => {
  24. return parseFloat(number.toFixed(x));
  25. }
  26. /**
  27. * 获取市场类型
  28. */
  29. const getMarketType = (mk) => {
  30. return mk == 0 ? 'early' : 'today';
  31. }
  32. /**
  33. * 更新联赛列表
  34. */
  35. const syncLeaguesList = ({ mk, leagues }) => {
  36. axios.post(`${BASE_URL}/syncLeague`, { mk, leagues })
  37. .then(res => {
  38. Logs.out('syncLeaguesList', res.data);
  39. })
  40. .catch(err => {
  41. Logs.out('syncLeaguesList', err.message);
  42. });
  43. }
  44. const updateLeaguesList = ({ mk, leagues }) => {
  45. const leaguesList = GAMES.Leagues;
  46. if (JSON.stringify(leaguesList[mk]) != JSON.stringify(leagues)) {
  47. leaguesList[mk] = leagues;
  48. syncLeaguesList({ mk, leagues });
  49. return leagues.length;
  50. }
  51. return 0;
  52. }
  53. /**
  54. * 获取筛选过的联赛
  55. */
  56. const getFilteredLeagues = async (mk) => {
  57. return axios.get(`${BASE_URL}/getLeagueTast?mk=${mk}`)
  58. .then(res => {
  59. if (res.data.code == 0) {
  60. return res.data.data;
  61. }
  62. return Promise.reject(new Error(res.data.message));
  63. });
  64. }
  65. /**
  66. * 同步比赛列表到服务器
  67. */
  68. const syncGamesList = ({ platform, mk, games }) => {
  69. axios.post(`${BASE_URL}/syncGames`, { platform, mk, games })
  70. .then(res => {
  71. Logs.out('syncGamesList', { platform, mk, count: games.length }, res.data);
  72. })
  73. .catch(err => {
  74. Logs.out('syncGamesList', { platform, mk }, err.message);
  75. });
  76. }
  77. /**
  78. * 同步基准比赛列表
  79. */
  80. const syncBaseList = ({ marketType, games }) => {
  81. const baseList = GAMES.Baselist;
  82. if (!baseList[marketType]) {
  83. baseList[marketType] = games;
  84. }
  85. const newMap = new Map(games.map(item => [item.eventId, item]));
  86. // 删除不存在的项
  87. for (let i = baseList[marketType].length - 1; i >= 0; i--) {
  88. if (!newMap.has(baseList[marketType][i].eventId)) {
  89. baseList[marketType].splice(i, 1);
  90. }
  91. }
  92. // 添加或更新
  93. const oldIds = new Set(baseList[marketType].map(item => item.eventId));
  94. games.forEach(game => {
  95. if (!oldIds.has(game.eventId)) {
  96. // 添加新项
  97. baseList[marketType].push(game);
  98. }
  99. });
  100. }
  101. /**
  102. * 更新比赛列表
  103. */
  104. const updateGamesList = (({ platform, mk, games } = {}) => {
  105. return new Promise((resolve, reject) => {
  106. if (!platform || !games) {
  107. return reject(new Error('PLATFORM_GAMES_INVALID'));
  108. }
  109. const marketType = getMarketType(mk);
  110. syncGamesList({ platform, mk, games });
  111. if (platform == 'ps') {
  112. syncBaseList({ marketType, games });
  113. }
  114. resolve();
  115. });
  116. });
  117. /**
  118. * 提交盘口数据
  119. */
  120. const submitOdds = ({ platform, mk, games }) => {
  121. // console.log('syncOdds', games);
  122. axios.post(`${BASE_URL}/syncOdds`, { platform, mk, games})
  123. .then(res => {
  124. Logs.out('syncOdds', { platform, mk, count: games.length }, res.data);
  125. })
  126. .catch(err => {
  127. Logs.out('syncOdds', { platform, mk }, err.message);
  128. });
  129. }
  130. /**
  131. * 同步基准盘口
  132. */
  133. const syncBaseEvents = ({ mk, games, outrights }) => {
  134. const marketType = getMarketType(mk);
  135. const baseList = GAMES.Baselist;
  136. if (!baseList[marketType]) {
  137. return;
  138. }
  139. const baseMap = new Map(baseList[marketType].map(item => [item.eventId, item]));
  140. games?.forEach(game => {
  141. const { eventId, evtime, events } = game;
  142. const baseGame = baseMap.get(eventId);
  143. if (baseGame) {
  144. baseGame.evtime = evtime;
  145. baseGame.events = events;
  146. }
  147. });
  148. outrights?.forEach(outright => {
  149. const { parentId, sptime, special } = outright;
  150. const baseGame = baseMap.get(parentId);
  151. if (baseGame) {
  152. baseGame.sptime = sptime;
  153. baseGame.special = special;
  154. }
  155. });
  156. if (games?.length) {
  157. const gamesList = baseList[marketType]?.map(game => {
  158. const { evtime, events, sptime, special, ...gameInfo } = game;
  159. const expireTime = Date.now() - 15000;
  160. let odds = {};
  161. if (evtime > expireTime) {
  162. odds = { ...odds, ...events };
  163. }
  164. if (sptime > expireTime) {
  165. odds = { ...odds, ...special };
  166. }
  167. const matches = PS_IOR_KEYS.map(([label, ...keys]) => {
  168. const match = keys.map(key => ({
  169. key,
  170. value: odds[key] ?? 0
  171. }));
  172. return {
  173. label,
  174. match
  175. };
  176. }).filter(item => item.match.every(entry => entry.value !== 0));
  177. return { ...gameInfo, matches };
  178. });
  179. // console.log('baseList', baseList[marketType]);
  180. submitOdds({ platform: 'ps', mk, games: gamesList });
  181. }
  182. }
  183. /**
  184. * 更新比赛盘口
  185. */
  186. const updateGamesEvents = ({ platform, mk, games, outrights }) => {
  187. return new Promise((resolve, reject) => {
  188. if (!platform || (!games && !outrights)) {
  189. return reject(new Error('PLATFORM_GAMES_INVALID'));
  190. }
  191. if (platform == 'ps') {
  192. syncBaseEvents({ mk, games, outrights });
  193. }
  194. resolve();
  195. });
  196. }
  197. /**
  198. * 获取关联比赛
  199. */
  200. const getGamesRelation = async (mk) => {
  201. return axios.get(`${BASE_URL}/getGameTast?mk=${mk}`)
  202. .then(res => {
  203. if (res.data.code == 0) {
  204. return res.data.data;
  205. }
  206. return Promise.reject(new Error(res.data.message));
  207. });
  208. }
  209. module.exports = {
  210. updateLeaguesList, getFilteredLeagues,
  211. updateGamesList, updateGamesEvents,
  212. getGamesRelation,
  213. }