scaler.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: stanley-king
  5. * Date: 2017/4/20
  6. * Time: 下午5:12
  7. */
  8. namespace bonus;
  9. class scaler
  10. {
  11. const match_rate = 30;
  12. private $mMoneys;
  13. private $mMatchMoney;
  14. public function __construct($rates_moneys)
  15. {
  16. $this->mMatchMoney = 0;
  17. $moneys = [];
  18. foreach ($rates_moneys as $rate => $money)
  19. {
  20. if($rate == self::match_rate) {
  21. $this->mMatchMoney += $money;
  22. }
  23. else {
  24. $val = [];
  25. $val['rate'] = $rate;
  26. $val['amount'] = $money;
  27. $moneys[] = $val;
  28. }
  29. }
  30. uasort($moneys,['\bonus\scaler','rate_desc']);
  31. $this->mMoneys = [];
  32. foreach ($moneys as $item) {
  33. $this->mMoneys[] = $item;
  34. }
  35. }
  36. private function match_money() {
  37. return $this->mMatchMoney * 100 / self::match_rate;
  38. }
  39. public function calc()
  40. {
  41. $total = $this->match_money();
  42. $count = count($this->mMoneys);
  43. if($count == 0) {
  44. return $this->format($total);
  45. }
  46. $max_rate = $this->mMoneys[0]['rate'];
  47. if($max_rate < self::match_rate) {
  48. return $this->format($total);
  49. }
  50. for($pos = $count - 1; $pos >= 0;)
  51. {
  52. $ret = $this->_calc($pos);
  53. if($ret == false) {
  54. $pos--;
  55. } else {
  56. $total += $ret;
  57. $total = intval($total * 100 + 0.5) / 100;
  58. return $this->format($total);
  59. }
  60. }
  61. return $this->format($total);
  62. }
  63. private function format($total)
  64. {
  65. $total = intval($total * 100 + 0.5);
  66. if($total == 0) {
  67. return false;
  68. }
  69. else {
  70. return $total / 100;
  71. }
  72. }
  73. private function _calc($pos)
  74. {
  75. $rate = $this->mMoneys[$pos]['rate'];
  76. $amount = $this->mMoneys[$pos]['amount'];
  77. $y = intval($amount * 100 + 0.5);
  78. if($rate > self::match_rate)
  79. { //满足条件,用0折扣红包抵扣
  80. $this->_calc_AB($pos + 1,$A,$B);
  81. return $B + ($A* 100 - self::match_rate * $B) / (self::match_rate);
  82. }
  83. else
  84. {
  85. $this->_calc_AB($pos,$A,$B);
  86. $need_amount = ($A * 100 - self::match_rate * $B) * $rate / ((self::match_rate - $rate) * 100);
  87. $x = intval($need_amount * 100 + 0.5);
  88. if($x < 0) { //此时达不到匹配的折扣率
  89. return false;
  90. }
  91. elseif($x == 0) { //前一个恰好抵扣
  92. return $B;
  93. }
  94. else
  95. {
  96. if($x <= $y) { //当前不满足全部抵扣
  97. return $B + ($x / $rate);
  98. }
  99. else { //当前还需要用0折扣红包抵扣
  100. $this->_calc_AB($pos + 1,$A,$B);
  101. return $B + ($A * 100 - self::match_rate * $B) / (self::match_rate);
  102. }
  103. }
  104. }
  105. }
  106. private function _calc_AB($pos,&$A,&$B)
  107. {
  108. $A = 0;
  109. for ($i = 0; $i < $pos; $i++) {
  110. $amount = $this->mMoneys[$i]['amount'];
  111. $A += $amount;
  112. }
  113. $B = 0;
  114. for ($i = 0; $i < $pos; $i++) {
  115. $amount = $this->mMoneys[$i]['amount'];
  116. $rate = $this->mMoneys[$i]['rate'];
  117. $B += $amount * 100 / $rate;
  118. }
  119. }
  120. static public function rate_desc($left,$right)
  121. {
  122. $t_l = intval($left['rate']);
  123. $t_r = intval($right['rate']);
  124. if($t_l > $t_r) return -1;
  125. elseif($t_l < $t_r) return 1;
  126. else return 0;
  127. }
  128. }