totalProfitCalc.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. const GOLD_BASE = 10000;
  2. const fixFloat = (number, x = 2) => {
  3. return parseFloat(number.toFixed(x));
  4. }
  5. const HandicapCalc = function (data) {
  6. const { i, g, a, b, c, w, l } = data;
  7. const t = w + l;
  8. const calcTemplate = (handlers) => {
  9. if (i > 2 || i < 0) {
  10. return {};
  11. }
  12. if (i === 2) {
  13. const z = g;
  14. const x = (b + 1) * (t + z) / (a * b - 1);
  15. const y = (a + 1) * (t + z) / (a * b - 1);
  16. return { x, y, z };
  17. };
  18. return handlers[i]?.() ?? {};
  19. };
  20. return {
  21. la_wh_wa() {
  22. return calcTemplate([
  23. () => {
  24. const x = g;
  25. const z = (t + x) / (2 * c + 1);
  26. const y = (c + 1) * (t + x) / (c + 0.5) / b;
  27. return { x, y, z };
  28. },
  29. () => {
  30. const y = g;
  31. const z = ((a + 1) * t + (1 - a * b / 2) * y) / (a * c - 1);
  32. const x = ((c + 1) * t + (c - b / 2) * y) / (a * c - 1);
  33. return { x, y, z };
  34. }
  35. ]);
  36. },
  37. la_dr_wa() {
  38. return calcTemplate([
  39. () => {
  40. const x = g;
  41. const z = (t + x) / c;
  42. const y = (t + x + z) / b;
  43. return { x, y, z };
  44. },
  45. () => {
  46. const y = g;
  47. const z = ((a + 1) * t + y) / (a * c - 1);
  48. const x = ((c + 1) * t + c * y) / (a * c - 1);
  49. return { x, y, z };
  50. }
  51. ]);
  52. },
  53. la_lh_wa() {
  54. return calcTemplate([
  55. () => {
  56. const x = g;
  57. const z = (2 * b + 1) * (t + x) / (2 * b * c - 1);
  58. const y = (c + 1) * (t + x) / (b * c - 0.5);
  59. return { x, y, z };
  60. },
  61. () => {
  62. const y = g;
  63. const z = ((a + 1) * t + (a / 2 + 1) * y) / (a * c - 1);
  64. const x = ((c + 1) * t + (c + 0.5) * y) / (a * c - 1);
  65. return { x, y, z };
  66. }
  67. ]);
  68. },
  69. lh_dr_wa() {
  70. return calcTemplate([
  71. () => {
  72. const x = g;
  73. const z = (t + x / 2) / c;
  74. const y = (t + x + z) / b;
  75. return { x, y, z };
  76. },
  77. () => {
  78. const y = g;
  79. const z = ((2 * a + 1) * t + y) / (2 * a * c - 1);
  80. const x = ((c + 1) * t + c * y) / (a * c - 0.5);
  81. return { x, y, z };
  82. }
  83. ]);
  84. },
  85. lh_lh_wa() {
  86. return calcTemplate([
  87. () => {
  88. const x = g;
  89. const z = ((2 * b + 1) * t + (b + 1) * x) / (2 * b * c - 1);
  90. const y = ((c + 1) * t + (c + 0.5) * x) / (b * c - 0.5);
  91. },
  92. () => {
  93. const y = g;
  94. const z = ((2 * a + 1) * t + (a + 1) * y) / (2 * a * c - 1);
  95. const x = ((c + 1) * t + (c + 0.5) * y) / (a * c - 0.5);
  96. return { x, y, z };
  97. }
  98. ]);
  99. },
  100. la_la_wa() {
  101. return calcTemplate([
  102. () => {
  103. const x = g;
  104. const z = (b + 1) * (t + x) / (b * c - 1);
  105. const y = (c + 1) * (t + x) / (b * c - 1);
  106. return { x, y, z };
  107. },
  108. () => {
  109. const y = g;
  110. const z = (a + 1) * (t + y) / (a * c - 1);
  111. const x = (c + 1) * (t + y) / (a * c - 1);
  112. return { x, y, z };
  113. }
  114. ]);
  115. }
  116. }
  117. }
  118. const calcExternalHandicap = (data) => {
  119. const { gold_side_jc: g, odds_side_a: a, odds_side_b: b, odds_side_m: c, jc_index: i, cross_type: t, win_target: w, pre_loss } = data;
  120. const l = pre_loss ?? 0;
  121. const calc = new HandicapCalc({ i, g, a, b, c, w, l });
  122. const { x, y, z } = calc?.[t]() ?? {};
  123. return {
  124. gold_side_a: fixFloat(x),
  125. gold_side_b: fixFloat(y),
  126. gold_side_m: fixFloat(z),
  127. jc_index: i,
  128. }
  129. }
  130. const calcGoldsWithWinTarget = (data) => {
  131. const { gold_side_jc, win_target, sol1, sol2 } = data;
  132. const {
  133. gold_side_a: goldA1,
  134. gold_side_b: goldB1,
  135. gold_side_m: goldM1,
  136. jc_index: jc_index_1
  137. } = calcExternalHandicap({ ...sol1, gold_side_jc, win_target });
  138. let pre_loss = 0, jc_win_1 = 0;
  139. switch (jc_index_1) {
  140. case 0:
  141. pre_loss = goldB1 + goldM1;
  142. jc_win_1 = GOLD_BASE * (sol1.odds_side_a + 1);
  143. break;
  144. case 1:
  145. pre_loss = goldA1 + goldM1;
  146. jc_win_1 = GOLD_BASE * (sol1.odds_side_b + 1);
  147. break;
  148. case 2:
  149. pre_loss = goldA1 + goldB1;
  150. jc_win_1 = GOLD_BASE * (sol1.odds_side_m + 1)
  151. break;
  152. }
  153. let {
  154. gold_side_a: goldA2,
  155. gold_side_b: goldB2,
  156. gold_side_m: goldM2,
  157. jc_index: jc_index_2
  158. } = calcExternalHandicap({ ...sol2, gold_side_jc, win_target, pre_loss });
  159. let jc_odds_2 = 0, win_target_2 = 0;
  160. switch (jc_index_2) {
  161. case 0:
  162. goldA2 = jc_win_1;
  163. jc_odds_2 = sol2.odds_side_a + 1;
  164. win_target_2 = goldA2 * jc_odds_2 - goldB2 - goldM2;
  165. break;
  166. case 1:
  167. goldB2 = jc_win_1;
  168. jc_odds_2 = sol2.odds_side_b + 1;
  169. win_target_2 = goldB2 * jc_odds_2 - goldA2 - goldM2;
  170. break;
  171. case 2:
  172. goldM2 = jc_win_1;
  173. jc_odds_2 = sol2.odds_side_m + 1;
  174. win_target_2 = goldM2 * jc_odds_2 - goldA2 - goldB2;
  175. break;
  176. }
  177. const win_jc = fixFloat(win_target_2 - GOLD_BASE - goldB2 - goldM2);
  178. return {
  179. goldA1,
  180. goldB1,
  181. goldM1,
  182. goldA2,
  183. goldB2,
  184. goldM2,
  185. win_jc,
  186. jc_index_1,
  187. jc_index_2,
  188. jc_base: GOLD_BASE,
  189. }
  190. }
  191. const calcTotalProfit = (sol1, sol2, gold_side_jc) => {
  192. const winTarget1 = sol1.win_average;
  193. const winTarget2 = sol2.win_average;
  194. const winTarget = fixFloat(Math.min(winTarget1, winTarget2), 2);
  195. const win1 = calcGoldsWithWinTarget({ gold_side_jc, win_target: winTarget1, sol1, sol2 })?.win_jc;
  196. const win2 = calcGoldsWithWinTarget({ gold_side_jc, win_target: winTarget2, sol1, sol2 })?.win_jc;
  197. const winJc = fixFloat(Math.max(win1, win2), 2);
  198. const start = Math.max(winTarget, winJc);
  199. const end = Math.min(winTarget, winJc);
  200. const result = [];
  201. for (let i = start; i > end; i--) {
  202. const win_target = i;
  203. const goldsInfo = calcGoldsWithWinTarget({ gold_side_jc, win_target, sol1, sol2 });
  204. const win_diff = Math.abs(fixFloat(win_target - goldsInfo.win_jc));
  205. const lastResult = result.at(-1);
  206. if (!lastResult?.win_diff || win_diff < lastResult.win_diff) {
  207. result.push({ win_target: fixFloat(win_target), win_diff, ...goldsInfo });
  208. }
  209. else {
  210. break;
  211. }
  212. }
  213. return result.at(-1);
  214. }
  215. module.exports = calcTotalProfit;