mratio_control.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. namespace refill;
  3. use Log;
  4. class mratio_control
  5. {
  6. private $mTimesConfig; //对应refill.ini 配置文件数据
  7. private $mGrossRatios;
  8. private $mDetailRatios;
  9. private $mMixedPrices;
  10. public function __construct()
  11. {
  12. $this->mTimesConfig = [];
  13. $this->mGrossRatios = [];
  14. $this->mDetailRatios = [];
  15. $this->mMixedPrices = [];
  16. }
  17. public function load()
  18. {
  19. global $config;
  20. $this->mTimesConfig = $config['merchant_retry_times'] ?? [];
  21. }
  22. public function update($gross_ratios, $detail_ratios)
  23. {
  24. if (!empty($gross_ratios)) {
  25. $this->mGrossRatios = $gross_ratios;
  26. }
  27. if (!empty($detail_ratios)) {
  28. $this->mDetailRatios = $detail_ratios;
  29. }
  30. }
  31. public function setMixedPrice($mchid, $mixed_quality, $card_type, $spec, $prices)
  32. {
  33. $key = "{$card_type}-{$spec}";
  34. $this->mMixedPrices[$mchid][$mixed_quality][$key] = $prices;
  35. }
  36. //获取售价和进价
  37. private function getPrice($mchid, $mixed_quality, $card_type, $spec)
  38. {
  39. $key = "{$card_type}-{$spec}";
  40. if (array_key_exists($mchid, $this->mMixedPrices))
  41. {
  42. $prices = $this->mMixedPrices[$mchid];
  43. if (array_key_exists($mixed_quality, $prices))
  44. {
  45. $qprices = $prices[$mixed_quality];
  46. if (array_key_exists($key, $qprices)) {
  47. $price = $qprices[$key];
  48. return $price;
  49. }
  50. }
  51. }
  52. return false;
  53. }
  54. public function total($mchid)
  55. {
  56. if (array_key_exists($mchid, $this->mTimesConfig)) {
  57. $items = $this->mTimesConfig[$mchid]['qualities'];
  58. $times = 0;
  59. $secs = 0;
  60. foreach ($items as $quality => $val) {
  61. $times += $val['times'] ?? 1;
  62. $secs += $val['secs'] ?? 180;
  63. }
  64. return [true, $times, $secs];
  65. } else {
  66. return [false, 0, 0];
  67. }
  68. }
  69. public function times($mchid, $quality)
  70. {
  71. if (array_key_exists($mchid, $this->mTimesConfig)) {
  72. $items = $this->mTimesConfig[$mchid]['qualities'] ?? [];
  73. if (array_key_exists($quality, $items)) {
  74. return $items[$quality]['times'];
  75. }
  76. }
  77. return false;
  78. }
  79. public function seconds($mchid, $quality)
  80. {
  81. if (array_key_exists($mchid, $this->mTimesConfig)) {
  82. $items = $this->mTimesConfig[$mchid]['qualities'] ?? [];
  83. if (array_key_exists($quality, $items)) {
  84. return $items[$quality]['secs'];
  85. }
  86. }
  87. return false;
  88. }
  89. public function exist($mchid)
  90. {
  91. if (array_key_exists($mchid, $this->mTimesConfig)) {
  92. return true;
  93. } else {
  94. return false;
  95. }
  96. }
  97. private function lower_ratio($mchid)
  98. {
  99. $lower_ratio = $this->mTimesConfig[$mchid]['lower_ratio'] ?? [];
  100. return [$lower_ratio['ratio'], $lower_ratio['period']];
  101. }
  102. private function profit_ratio($mchid) {
  103. $profit_ratio = $this->mTimesConfig[$mchid]['profit_ratio'] ?? 0.0;
  104. return $profit_ratio;
  105. }
  106. private function gross_ratio($mchid, $period)
  107. {
  108. $mratios = $this->mGrossRatios;
  109. if (array_key_exists($mchid, $mratios)) {
  110. $mratios = $mratios[$mchid];
  111. if (array_key_exists($period, $mratios)) {
  112. return $mratios[$period];
  113. }
  114. }
  115. return [0, 0, 1.0];
  116. }
  117. private function detail_ratio($mchid, $quality, $card_type, $spec, $period)
  118. {
  119. $key = "{$mchid}-{$quality}-{$card_type}-{$spec}";
  120. if(array_key_exists($key,$this->mDetailRatios)) {
  121. $ratios = $this->mDetailRatios[$key];
  122. if(array_key_exists($period,$ratios)) {
  123. return $ratios[$period];
  124. }
  125. }
  126. return [0, 0, 1.0];
  127. }
  128. private function detail_ratios($mchid,$qualities,$card_type, $spec,$period)
  129. {
  130. $result = [];
  131. foreach ($qualities as $quality) {
  132. $ret = $this->detail_ratio($mchid,$quality,$card_type,$spec,$period);
  133. $result[$quality] = $ret;
  134. }
  135. return $result;
  136. }
  137. public function ratio_match($mchid, $org_quality, $cur_quality, $card_type, $spec,$qualities)
  138. {
  139. $header = __METHOD__ . " mchid={$mchid} card_type={$card_type} spec={$spec}";
  140. [$ratio, $period] = $this->lower_ratio($mchid);
  141. [$_succ, $_fail, $gross_ratio] = $this->gross_ratio($mchid, $period);
  142. Log::record("{$header} gross_ratio = {$gross_ratio},lower_ratio={$ratio}",Log::DEBUG);
  143. if($gross_ratio >= $ratio) return true;
  144. [$_succ, $_fail, $cur_ratio] = $this->detail_ratio($mchid, $cur_quality, $card_type, $spec, $period);
  145. Log::record("{$header} cur_ratio = {$cur_ratio},lower_ratio={$ratio}",Log::DEBUG);
  146. if($cur_ratio >= $ratio) return true;
  147. if (!PolicyUtil::mixed_quality($org_quality)) {
  148. return false;
  149. }
  150. $prices = $this->getPrice($mchid, $org_quality, $card_type, $spec);
  151. if ($prices === false) {
  152. return false;
  153. }
  154. $dratios = $this->detail_ratios($mchid, $qualities,$card_type, $spec, $period);
  155. $profit_ratio = $this->profit_ratio($mchid);
  156. $profit_judger = function ($org_quality,$qualities,$prices,$dratios,$profit_ratio) use ($header)
  157. {
  158. $sale = $prices[$org_quality];
  159. $profit = 0;
  160. $amount = 0;
  161. foreach ($qualities as $quality) {
  162. $inprice = $prices[$quality] ?? false;
  163. if ($inprice === false) continue;
  164. [$succ, $fail, $ratio] = $dratios[$quality];
  165. $profit += $succ * ($sale - $inprice);
  166. $amount += $succ * $sale;
  167. }
  168. $cur_pratio = round(($profit + 0.00001) / ($amount + 0.00001),4);
  169. $profit_ratio = round($profit_ratio,4);
  170. Log::record("{$header} cur_pratio = {$cur_pratio},profit_ratio={$profit_ratio}",Log::DEBUG);
  171. return $cur_pratio > $profit_ratio;
  172. };
  173. $can_next = $profit_judger($org_quality,$qualities,$prices,$dratios,$profit_ratio);
  174. return !$can_next;
  175. }
  176. }