scaler.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. //todo modify usort
  32. $this->mMoneys = [];
  33. foreach ($moneys as $item) {
  34. $this->mMoneys[] = $item;
  35. }
  36. }
  37. private function match_money() {
  38. return $this->mMatchMoney * 100 / self::match_rate;
  39. }
  40. public function calc()
  41. {
  42. $total = $this->match_money();
  43. $count = count($this->mMoneys);
  44. if($count == 0) {
  45. return $this->format($total);
  46. }
  47. $max_rate = $this->mMoneys[0]['rate'];
  48. if($max_rate < self::match_rate) {
  49. return $this->format($total);
  50. }
  51. for($pos = $count - 1; $pos >= 0;)
  52. {
  53. $ret = $this->_calc($pos);
  54. if($ret == false) {
  55. $pos--;
  56. } else {
  57. $total += $ret;
  58. $total = intval($total * 100 + 0.5) / 100;
  59. return $this->format($total);
  60. }
  61. }
  62. return $this->format($total);
  63. }
  64. private function format($total)
  65. {
  66. $total = intval($total * 100 + 0.5);
  67. if($total == 0) {
  68. return false;
  69. }
  70. else {
  71. return $total / 100;
  72. }
  73. }
  74. private function _calc($pos)
  75. {
  76. $rate = $this->mMoneys[$pos]['rate'];
  77. $amount = $this->mMoneys[$pos]['amount'];
  78. $y = intval($amount * 100 + 0.5);
  79. if($rate > self::match_rate)
  80. { //满足条件,用0折扣红包抵扣
  81. $this->_calc_AB($pos + 1,$A,$B);
  82. return $B + ($A* 100 - self::match_rate * $B) / (self::match_rate);
  83. }
  84. else
  85. {
  86. $this->_calc_AB($pos,$A,$B);
  87. $need_amount = ($A * 100 - self::match_rate * $B) * $rate / ((self::match_rate - $rate) * 100);
  88. $x = intval($need_amount * 100 + 0.5);
  89. if($x < 0) { //此时达不到匹配的折扣率
  90. return false;
  91. }
  92. elseif($x == 0) { //前一个恰好抵扣
  93. return $B;
  94. }
  95. else
  96. {
  97. if($x <= $y) { //当前不满足全部抵扣
  98. return $B + ($x / $rate);
  99. }
  100. else { //当前还需要用0折扣红包抵扣
  101. $this->_calc_AB($pos + 1,$A,$B);
  102. return $B + ($A * 100 - self::match_rate * $B) / (self::match_rate);
  103. }
  104. }
  105. }
  106. }
  107. private function _calc_AB($pos,&$A,&$B)
  108. {
  109. $A = 0;
  110. for ($i = 0; $i < $pos; $i++) {
  111. $amount = $this->mMoneys[$i]['amount'];
  112. $A += $amount;
  113. }
  114. $B = 0;
  115. for ($i = 0; $i < $pos; $i++) {
  116. $amount = $this->mMoneys[$i]['amount'];
  117. $rate = $this->mMoneys[$i]['rate'];
  118. $B += $amount * 100 / $rate;
  119. }
  120. }
  121. static public function rate_desc($left,$right)
  122. {
  123. $t_l = intval($left['rate']);
  124. $t_r = intval($right['rate']);
  125. if($t_l > $t_r) return -1;
  126. elseif($t_l < $t_r) return 1;
  127. else return 0;
  128. }
  129. }