<?php
/**
 * Created by PhpStorm.
 * User: stanley-king
 * Date: 2017/4/20
 * Time: 下午5:12
 */

namespace bonus;


class scaler
{
    const match_rate = 30;

    private $mMoneys;
    private $mMatchMoney;

    public function __construct($rates_moneys)
    {
        $this->mMatchMoney = 0;

        $moneys = [];
        foreach ($rates_moneys as $rate => $money)
        {
            if($rate == self::match_rate) {
                $this->mMatchMoney += $money;
            }
            else {
                $val = [];
                $val['rate'] = $rate;
                $val['amount'] = $money;

                $moneys[] = $val;
            }
        }
        uasort($moneys,['\bonus\scaler','rate_desc']);

        $this->mMoneys = [];
        foreach ($moneys as $item) {
            $this->mMoneys[] = $item;
        }
    }
    private function match_money() {
        return $this->mMatchMoney * 100 / self::match_rate;
    }

    public function calc()
    {
        $total = $this->match_money();

        $count = count($this->mMoneys);
        if($count == 0) {
            return $this->format($total);
        }
        $max_rate = $this->mMoneys[0]['rate'];
        if($max_rate < self::match_rate) {
            return $this->format($total);
        }

        for($pos = $count - 1; $pos >= 0;)
        {
            $ret = $this->_calc($pos);
            if($ret == false) {
                $pos--;
            } else {
                $total += $ret;
                $total = intval($total * 100 + 0.5) / 100;
                return $this->format($total);
            }
        }
        return $this->format($total);
    }

    private function format($total)
    {
        $total = intval($total * 100 + 0.5);
        if($total == 0) {
            return false;
        }
        else {
            return $total / 100;
        }
    }

    private function _calc($pos)
    {
        $rate   = $this->mMoneys[$pos]['rate'];
        $amount = $this->mMoneys[$pos]['amount'];
        $y = intval($amount * 100 + 0.5);

        if($rate > self::match_rate)
        {   //满足条件，用0折扣红包抵扣
            $this->_calc_AB($pos + 1,$A,$B);
            return $B + ($A* 100 - self::match_rate * $B)  / (self::match_rate);
        }
        else
        {
            $this->_calc_AB($pos,$A,$B);
            $need_amount = ($A * 100 - self::match_rate * $B) * $rate / ((self::match_rate - $rate) * 100);
            $x = intval($need_amount * 100 + 0.5);

            if($x < 0) { //此时达不到匹配的折扣率
                return false;
            }
            elseif($x == 0) { //前一个恰好抵扣
                return $B;
            }
            else
            {
                if($x <= $y) { //当前不满足全部抵扣
                    return $B + ($x / $rate);
                }
                else { //当前还需要用0折扣红包抵扣
                    $this->_calc_AB($pos + 1,$A,$B);
                    return $B + ($A * 100 - self::match_rate * $B)  / (self::match_rate);
                }
            }
        }
    }

    private function _calc_AB($pos,&$A,&$B)
    {
        $A = 0;
        for ($i = 0; $i < $pos; $i++) {
            $amount = $this->mMoneys[$i]['amount'];
            $A += $amount;
        }

        $B = 0;
        for ($i = 0; $i < $pos; $i++) {
            $amount = $this->mMoneys[$i]['amount'];
            $rate = $this->mMoneys[$i]['rate'];
            $B += $amount * 100 / $rate;
        }
    }

    static public function rate_desc($left,$right)
    {
        $t_l = intval($left['rate']);
        $t_r = intval($right['rate']);

        if($t_l > $t_r) return -1;
        elseif($t_l < $t_r) return 1;
        else return 0;
    }
}