stanley-king il y a 2 ans
Parent
commit
a2f03cc021

+ 133 - 85
helper/refill/policy/mratio_controlex.php

@@ -6,6 +6,8 @@ use Log;
 
 class mratio_controlex
 {
+    const delta = 0.0000001;
+
     private $mTimesConfig; //对应refill.ini 配置文件数据
     private $mInterceptConfig;
 
@@ -76,11 +78,13 @@ class mratio_controlex
 
     private function load_intercept()
     {
-        $mch_configs = function () {
+        $mch_configs = function ()
+        {
             $result = [];
 
             $i = 0;
-            while (true) {
+            while (true)
+            {
                 $start = $i * 100;
                 $items = Model()->table('merchant')->where(['mchid' => ['gt', 0], 'merchant_state' => 1])->field('mchid,intercept_cfg')->order('mchid asc')->limit("{$start},100")->select();
                 if (empty($items)) {
@@ -88,19 +92,22 @@ class mratio_controlex
                 }
                 $i++;
 
-                foreach ($items as $item) {
+                foreach ($items as $item)
+                {
                     $mchid = intval($item['mchid']);
                     if ($mchid <= 0) continue;
 
                     $cfg = unserialize($item['intercept_cfg']);
                     if (empty($cfg)) continue;
 
-                    if (!empty($cfg['segment'])) {
+                    if (!empty($cfg['segment']))
+                    {
                         $segment = $cfg['segment'];
                         $sitems = explode(',', $segment);
 
                         $tmp = [];
-                        foreach ($sitems as $sitem) {
+                        foreach ($sitems as $sitem)
+                        {
                             $sitem = trim($sitem);
                             if (!empty($sitem)) {
                                 $tmp[] = $sitem;
@@ -158,7 +165,8 @@ class mratio_controlex
 
             $times = 0;
             $secs = 0;
-            foreach ($items as $quality => $val) {
+            foreach ($items as $quality => $val)
+            {
                 if (!in_array($quality, $qualities, true)) {
                     continue;
                 }
@@ -187,7 +195,8 @@ class mratio_controlex
 
     public function seconds($mchid, $quality)
     {
-        if (array_key_exists($mchid, $this->mTimesConfig)) {
+        if (array_key_exists($mchid, $this->mTimesConfig))
+        {
             $items = $this->mTimesConfig[$mchid]['qualities'] ?? [];
             if (array_key_exists($quality, $items)) {
                 return $items[$quality]['secs'];
@@ -206,31 +215,17 @@ class mratio_controlex
         }
     }
 
-    //{\"10202\":{\"ratio\":0.65,\"period\":86400,\"profit_ratio\":0.002,\"profit_formula\":\"all\"}
-    //to-do for test
-//    private function lowest_ratio($mchid)
-//    {
-//        $lower_ratio = $this->mTimesConfig[$mchid]['lower_ratio'] ?? [];
-//        if (empty($lower_ratio)) {
-//            return [0.30, 86400];
-//        } else {
-//            return [$lower_ratio['ratio'], $lower_ratio['period']];
-//        }
-//    }
-//
-//    private function profit_ratio($mchid) {
-//        $profit_ratio = $this->mTimesConfig[$mchid]['profit_ratio'] ?? 0.002;
-//        return $profit_ratio;
-//    }
-
+    private function profit_formula($mchid) {
+        return $this->mTimesConfig[$mchid]['profit_formula'] ?? 'qts';
+    }
 
     private function lowest_ratio($mchid)
     {
         $lower_ratio = $this->mTimesConfig[$mchid]['lower_ratio'] ?? [];
         if (empty($lower_ratio)) {
-            return [0.0, 3600];
+            return 0.0;
         } else {
-            return [$lower_ratio['ratio'], $lower_ratio['period']];
+            return $lower_ratio['ratio'];
         }
     }
 
@@ -262,94 +257,131 @@ class mratio_controlex
         return [0, 0, 0, 0, 0, 0];
     }
 
-    //return true 表示当前质量满足条件。
-    public function ratio_match($mchid, $org_quality, $card_type, $spec, $qualities)
+    //match: true 表示当前质量满足条件,可以不走溢价,false,表示可以走溢价
+    //can_last: true,能补充,false 表示不能走溢价
+    public function ratio_matchex($mchid, $org_quality, $card_type, $spec, $qualities)
     {
         if (count($qualities) <= 1) {
             return [true, true];
         }
 
+        $lowest_ratio = $this->lowest_ratio($mchid);
+        $lowest_pratio = $this->profit_ratio($mchid);
+        $profit_formula = $this->profit_formula($mchid);
         $header = __METHOD__ . " mchid={$mchid} card_type={$card_type} spec={$spec}";
-        [$lowest_ratio, $period] = $this->lowest_ratio($mchid);
 
-        $lowest_pratio = $this->profit_ratio($mchid);
-        [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
-        Log::record("{$header} gross_ratio={$gross_ratio}, lower_ratio={$lowest_ratio}", Log::DEBUG);
+        Log::record("{$header} formula={$profit_formula}, lowest_ratio={$lowest_ratio} lowest_pratio={$lowest_pratio}", Log::DEBUG);
 
-        if ($gross_pratio > $lowest_pratio) {
-            $can_last = true;
-        } else {
-            $can_last = false;
-        }
+        $formula = $this->profit_formula($mchid);
+        Log::record("{$header} formula = {$formula}",Log::DEBUG);
 
-        if (!PolicyUtil::mixed_quality($org_quality))
+        if($formula === 'all')
         {
-            if ($gross_ratio >= $lowest_ratio) {
-                return [true,true];
+            [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
+            Log::record("{$header} gross_ratio={$gross_ratio}, gross_pratio={$gross_pratio}", Log::DEBUG);
+
+            if ($gross_pratio > $lowest_pratio) {
+                $can_last = true;
+            } else {
+                $can_last = false;
+            }
+
+            if (!PolicyUtil::mixed_quality($org_quality))
+            {
+                if ($gross_ratio >= $lowest_ratio) {
+                    return [true,true];
+                } else {
+                    return [false,true];
+                }
+            }
+            elseif ($gross_ratio >= $lowest_ratio) {
+                $match = $this->pre_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
+                return [$match,$can_last];
             } else {
-                return [false,true];
+                $match = $this->all_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
+                return [$match,$can_last];
             }
         }
-        elseif ($gross_ratio >= $lowest_ratio) {
-            $match = $this->pre_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
-            return [$match,$can_last];
-        } else {
-            $match = $this->all_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
-            return [$match,$can_last];
+        elseif($formula === 'qt') {
+            return $this->qts_checker($mchid, $org_quality,$cur_quality, $card_type, $spec, $qualities,$period,$header,$ratio);
         }
+        else {
+            return $this->qts_checker($mchid, $org_quality,$cur_quality, $card_type, $spec, $qualities,$period,$header,$ratio);
+        }
+
+
+        [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
+        Log::record("{$header} gross_ratio={$gross_ratio}, lower_ratio={$lowest_ratio}", Log::DEBUG);
+
+
     }
 
     private function pre_checker($mchid, $card_type, $spec, $header, $lowest_ratio)
     {
-        $ts_ratios = function ($mchid, $type_specs, $all_submit)
+        //计算各个card_type,spec 提交订单的占比情况,及所有面额
+        $spec_ratios = function ($mchid, $type_specs, $all_submit)
         {
-            $result = [];
+            $specs = [];
+            $spec_details = [];
+            foreach ($type_specs as $item)
+            {
+                [$card_type, $spec] = $item;
+                if(!in_array($spec,$spec_details)) {
+                    $spec_details[] = $spec;
+                    $specs[] = $spec;
+                }
 
-            if ($all_submit == 0) {
-                $all_submit += 0.00001;
+                [$submit_count, $succ_count, $fail_count, $cur_ratio, $profit, $cur_pratio] = $this->detail_ratio($mchid, $card_type, $spec);
+                $spec_details[$spec][] = [$submit_count, $succ_count, $fail_count, $cur_ratio, $profit, $cur_pratio];
             }
 
-            foreach ($type_specs as $item) {
-                [$card_type, $spec] = $item;
-                [$submit_count, $succ_count, $fail_count, $cur_ratio, $profit, $cur_pratio] = $this->detail_ratio($mchid, $card_type, $spec);
-                $submit_ratio = $submit_count / $all_submit;
+            $ratios = [];
+            foreach ($spec_details as $spec => $details)
+            {
+                [$submit_count, $succ_count, $fail_count] = [0, 0, 0];
+                foreach ($details as $item) {
+                    [$_submit_count, $_succ_count, $_fail_count, $_cur_ratio, $_profit, $_cur_pratio] = $item;
+                    $submit_count += $_submit_count;
+                    $succ_count += $_succ_count;
+                    $fail_count += $_fail_count;
+                }
+                $submit_ratio = $submit_count / ($all_submit + self::delta);
+                $cur_ratio = $succ_count / ($succ_count + $fail_count + self::delta);
 
-                $result[] = [$card_type, $spec, $submit_ratio, $cur_ratio, $cur_pratio];
+                $ratios[$spec] = [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio];
             }
 
-            return $result;
+            return [$specs, $ratios];
         };
 
-        $spec_extract = function ($item) {
-            [$card_type, $spec, $submit_ratio, $cur_ratio, $cur_pratio] = $item;
-            return $spec;
-        };
+        $split_array
 
-        $ts_sorter_spec = function ($left, $right) use ($spec_extract)
+        //找出最佳补充面额
+        $ts_filter = function ($all_submit, $specs, $spec_details, $ratio, $lowest_ratio)
         {
-            $l = $spec_extract($left);
-            $r = $spec_extract($right);
-
-            if ($l > $r)
-                return 1;
-            elseif ($l < $r)
-                return -1;
-            else
-                return 0;
-        };
+            $count = count($specs);
+            if ($count === 1) {
+                return true;
+            }
 
-        $ts_filter = function ($ts_ratios, $ratio, $lowest_ratio)
-        {
+
+            for ($i = 1; $i < $count; $i++)
+            {
+                end()
+
+            }
+
+            $mast_succs = intval($all_submit * $lowest_ratio);
             $result = [];
 
             $all = 0.00;
-            foreach ($ts_ratios as $item)
+            foreach ($spec_details as $item)
             {
                 [$card_type, $spec, $submit_ratio, $cur_ratio, $cur_pratio] = $item;
                 $all += $submit_ratio * $cur_ratio;
 
-                $r = $all / ($lowest_ratio + 0.00001);
-                if ($r > $ratio)
+                $r = $all / ($lowest_ratio + self::delta);
+                if ($r > 1)
                     break;
                 else {
                     $result[] = "{$card_type}-{$spec}";
@@ -358,6 +390,7 @@ class mratio_controlex
             return $result;
         };
 
+
         $lowest_pratio = $this->profit_ratio($mchid);
         [$all_submit, $succ_count, $fail_count, $gross_ratio, $profit, $cur_pratio] = $this->gross_ratio($mchid);
 
@@ -365,16 +398,30 @@ class mratio_controlex
             return true;
         }
 
-        $type_specs = $this->mMchQTS[$mchid];
-        $ts_ratios = $ts_ratios($mchid, $type_specs, $all_submit);
-        usort($ts_ratios, $ts_sorter_spec);
-
-        $ratio = $gross_ratio / ($lowest_ratio + 0.00001);
+        $ratio = $gross_ratio / ($lowest_ratio + self::delta);
+        if ($lowest_pratio >= 0.95) {
+            $max_ratio = 1.0;
+        }
+        elseif($lowest_pratio >= 0.90) {
+            $max_ratio = 1.02;
+        }
+        elseif ($lowest_pratio >= 0.5) {
+            $max_ratio = 1.05;
+        }
+        else {
+            $max_ratio = 1.07;
+        }
 
-        if ($ratio > 1.1) {
+        if($ratio >= $max_ratio) {
             return true;
-        } else {
-            $meet = $ts_filter($ts_ratios, $ratio, $lowest_ratio);
+        }
+        else
+        {
+            $type_specs = $this->mMchQTS[$mchid];
+            [$specs, $spec_ratios] = $spec_ratios($mchid, $type_specs, $all_submit);
+            sort($specs);
+
+            $meet = $ts_filter($all_submit, $spec_ratios, $ratio, $lowest_ratio);
             $exist = array_key_exists("{$card_type}-{$spec}", $meet);
             return !$exist;
         }
@@ -392,6 +439,7 @@ class mratio_controlex
         }
     }
 
+    //机构订单拦截
     public function need_intercept($mchid, $card_type, $card_state, $is_transfer, $card_no): bool
     {
         $start_with = function ($card_no, $segment) {

+ 10 - 11
plot/refill/MProfitRatioCalc.py

@@ -37,7 +37,7 @@ class MProfitRatioCalc(MerchantCalc):
         _fix = False
         for mchid, period, formula in mixed_ratios:
             logger.debug(f'mchid={mchid} period={period}')
-            end_time = int(time.time())
+            end_time = int(time.time()) - 86400
             if period == 86401:
                 cur_day = day_stamp(end_time)
                 period = end_time - cur_day
@@ -73,38 +73,37 @@ class MProfitRatioCalc(MerchantCalc):
                     profit_ratio = round(profit / (amount + 0.0000001), 6)
                     detail[key] = [submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio]
 
-                    if _card_type not in type_detail:
+                    if _card_type not in types_detail:
                         types_detail[_card_type] = []
                     types_detail[_card_type].append((submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio, _spec))
 
-            _mch_type_detail = self._calc_types_detail(types_detail)
-            types[_mchid] = _mch_type_detail
+            _mch_type_detail = self._calc_types_detail(mchid, types_detail)
+            types.update(_mch_type_detail)
 
-
-        result = {'gross': gross, 'detail': detail}
+        result = {'gross': gross, 'detail': detail, 'types': types}
+        logger.debug(f'profit_ratio={result}')
         if len(gross) != 0 or len(detail) != 0:
             rclient.set(f"nc_refill_merchant_profit_ratio", json.dumps(result))
             rclient.publish('refill', json.dumps({'type': 'mch_profit_ratio', 'value': 0}))
 
         return 1
 
-    def _calc_types_detail(self, types_detail):
+    def _calc_types_detail(self, _mchid, types_detail):
         result = {}
         for _card_type, vals in types_detail.items():
+            key = f'{_mchid}-{_card_type}'
             submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio = 0, 0, 0, 0.0, 0.0, 0.0
             spec_amount = 0
             for item in vals:
                 _submit_count, _succ_count, _fail_count, _succ_ratio, _profit, _profit_ratio, _spec = item
                 submit_count += _submit_count
                 succ_count += _succ_count
-                fail_count += fail_count
+                fail_count += _fail_count
                 profit += _profit
                 spec_amount += _spec * _succ_count
 
             succ_ratio = round(succ_count / (succ_count + fail_count + 0.0000001), 6)
             profit_ratio = round(profit / (spec_amount + 0.000001), 6)
 
-            types_detail[_card_type] = [submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio]
-
+            result[key] = [submit_count, succ_count, fail_count, succ_ratio, profit, profit_ratio]
         return result
-

+ 1 - 1
plot/refill/algorithm.py

@@ -254,7 +254,7 @@ def calc_mch_profit(data, pos_map: type(EMchPosmap), start: int, end: int):
     mch_amounts = sums[pos_map.succ_mch_amounts]
     profit = mch_amounts - ch_amounts
 
-    return int(submit_count), int(succ_count), int(fail_count), round(succ_ratio, 5), round(profit, 3)
+    return int(submit_count), int(succ_count), int(fail_count), round(succ_ratio, 6), round(profit, 4)
 
 
 def calc_cov_netfail(data, pos_map, start, end, window):

+ 7 - 0
test/TestError.php

@@ -58,4 +58,11 @@ class TestError extends PHPUnit_Framework_TestCase
         $x = '%7B%22openid%22%3A%22oQH7D5F4UnDMpXhcqqbrEDyB04d4%22%2C%22nickName%22%3A%22Meloo%22%2C%22gender%22%3A1%2C%22language%22%3A%22zh_CN%22%2C%22city%22%3A%22Jinshan%22%2C%22province%22%3A%22Shanghai%22%2C%22country%22%3A%22China%22%2C%22avatarUrl%22%3A%22https%3A%2F%2Fwx.qlogo.cn%2Fmmopen%2Fvi_32%2FQ0j4TwGTfTKTH8blznqPjwIMFlazvEcVOXZ52Fo6hBWdmtXc3vwIo1eteQHOWCQGBjyEFRf25IRv8JhbfictdSA%2F132%22%2C%22nickname%22%3A%22Meloo%22%7D';
         $y = urldecode($x);
     }
+
+    public function testSlice()
+    {
+        $a=array("red","green","blue","yellow","brown");
+        $x1 = array_slice($a,0,1);
+        $x2 = array_slice($a,1);
+    }
 }