stanley-king 2 vuotta sitten
vanhempi
commit
961b39303a

+ 1 - 1
docker/compose/workcuda/acc/docker-compose.yml

@@ -45,7 +45,7 @@ services:
     volumes:
       - ../../../../:/var/www/html
       - ../conf/etc/localtime:/etc/localtime:ro
-      - ../conf/php/php-debug.ini:/usr/local/etc/php/php.ini
+      - ../conf/php/php.ini:/usr/local/etc/php/php.ini
       - /mnt/upload:/var/www/html/data/upload
       - /mnt/shoplog:/var/www/html/data/log
       - ../conf/php/vapi-spwan-start:/usr/local/bin/docker-spwan-start

+ 1 - 1
docker/compose/workcuda/admin/docker-compose.yml

@@ -26,7 +26,7 @@ services:
     volumes:
       - ../../../../:/var/www/html
       - ../conf/etc/localtime:/etc/localtime:ro
-      - ../conf/php/php-debug.ini:/usr/local/etc/php/php.ini
+      - ../conf/php/php.ini:/usr/local/etc/php/php.ini
       - ../conf/php-fpm/php-fpm.conf:/usr/local/etc/php-fpm.conf
       - /mnt/upload:/var/www/html/data/upload
       - /mnt/shoplog:/var/www/html/data/log

+ 2 - 2
helper/refill/RefillBase.php

@@ -888,9 +888,9 @@ class RefillBase
     {
         return $this->mPolicy->region_intercept($quality,$card_type,$region_no);
     }
-    public function UpdateMchRatios($gross,$detail)
+    public function UpdateMchRatios($gross,$detail,$types)
     {
-        $this->mPolicy->update_mchratios($gross,$detail);
+        $this->mPolicy->update_mchratios($gross, $detail, $types);
     }
     public function UpdateChctl($params)
     {

+ 4 - 2
helper/refill/XYZRefillFactory.php

@@ -27,10 +27,12 @@ require_once(BASE_HELPER_PATH . '/refill/policy/PolicyUtil.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/xyz/quality_ploy.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/mgroup.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/channel_filter.php');
-
 require_once(BASE_HELPER_PATH . '/refill/policy/mratio_control.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/mratio_controlex.php');
-
+require_once(BASE_HELPER_PATH . '/refill/policy/match/mixed_match.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/match/whole_match.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/match/type_match.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/match/type_spec_match.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/overload_assigner.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/interceptor.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/transfer.php');

+ 1 - 1
helper/refill/policy/IPolicy.php

@@ -16,7 +16,7 @@ interface IPolicy
     public function need_intercept($mchid,$card_type,$card_state,$is_transfer,$card_no) : bool;
     public function region_intercept($quality,$card_type,$region_no) : bool;
 
-    public function update_mchratios($all,$detail);
+    public function update_mchratios($all,$detail,$types);
     public function update_chctl($speeds);
     public function update_maxspeeds($speeds);
 }

+ 1 - 1
helper/refill/policy/lingzh/policy.php

@@ -483,7 +483,7 @@ class policy extends ProviderManager implements IPolicy
         return strtoupper(md5($body));
     }
 
-    public function update_mchratios($gross,$detail)
+    public function update_mchratios($gross, $detail, $types)
     {
         $this->mRatioCtl->update($gross,$detail);
     }

+ 141 - 0
helper/refill/policy/match/ImateTester.php

@@ -0,0 +1,141 @@
+<?php
+
+namespace refill;
+
+class ImateTester
+{
+    private $mTimesConfig; //对应refill.ini 配置文件数据
+    private $mGrossRatios;
+    private $mTypeRatios;
+    private $mDetailRatios;
+    private $mMchQTS;
+
+    public function __construct()
+    {
+        $this->mTimesConfig = [];
+        $this->mGrossRatios = [];
+        $this->mTypeRatios = [];
+        $this->mDetailRatios = [];
+        $this->mMchQTS = [];
+    }
+
+    public function load()
+    {
+        $this->load_retry();
+    }
+
+    private function load_retry()
+    {
+        $isDay = functional::isDay();
+        $mch_configs = function ($isDay) {
+            $result = [];
+
+            $i = 0;
+            while (true) {
+                $start = $i * 100;
+                $items = Model()->table('merchant')->where(['mchid' => ['gt', 0], 'merchant_state' => 1])->field('mchid,retry_times_cfg')->order('mchid asc')->limit("{$start},100")->select();
+                if (empty($items)) {
+                    break;
+                }
+                $i++;
+
+                foreach ($items as $item) {
+                    $mchid = intval($item['mchid']);
+                    if ($mchid <= 0) continue;
+
+                    $retry_times_cfg = unserialize($item['retry_times_cfg']);
+                    if (empty($retry_times_cfg)) continue;
+
+                    $qualities = &$retry_times_cfg['qualities'];
+                    foreach ($qualities as $quality => $cfg) {
+                        if ($isDay) {
+                            $qualities[$quality]['secs'] = $cfg['day_secs'];
+                        } else {
+                            $qualities[$quality]['secs'] = $cfg['night_secs'];
+                        }
+                    }
+
+                    $result[$mchid] = $retry_times_cfg;
+                }
+            }
+
+            return $result;
+        };
+
+        $this->mTimesConfig = $mch_configs($isDay);
+    }
+
+    public function update($gross_ratios, $detail_ratios,$type_ratios)
+    {
+        if (!empty($gross_ratios)) {
+            $this->mGrossRatios = $gross_ratios;
+        }
+        if (!empty($type_ratios)) {
+            $this->mTypeRatios = $type_ratios;
+        }
+        if (!empty($detail_ratios)) {
+            $this->mDetailRatios = $detail_ratios;
+        }
+
+        $this->mMchQTS = [];
+        foreach ($detail_ratios as $key => $val) {
+            [$mchid, $card_type, $spec] = explode('-', $key);
+
+            $mchid = intval($mchid);
+            $card_type = intval($card_type);
+            $spec = intval($spec);
+
+            $this->mMchQTS[$mchid][] = [$card_type, $spec];
+        }
+    }
+    public function profit_formula($mchid) {
+        return $this->mTimesConfig[$mchid]['profit_formula'] ?? 'qts';
+    }
+
+    public function lowest_ratio($mchid)
+    {
+        $lower_ratio = $this->mTimesConfig[$mchid]['lower_ratio'] ?? [];
+        if (empty($lower_ratio)) {
+            return 0.0;
+        } else {
+            return $lower_ratio['ratio'];
+        }
+    }
+
+    public function profit_ratio($mchid)
+    {
+        $profit_ratio = $this->mTimesConfig[$mchid]['profit_ratio'] ?? 0.0;
+        return $profit_ratio;
+    }
+
+    public function type_specs($mchid)
+    {
+        if(array_key_exists($mchid,$this->mMchQTS)) {
+            return $this->mMchQTS[$mchid];
+        }
+        else {
+            return [];
+        }
+    }
+
+    //match: true 表示当前质量满足条件,可以不走溢价,false,表示可以走溢价
+    //can_last: true,能补充,false 表示不能走溢价
+    public function ratio_match($mchid, $org_quality, $card_type, $spec, $qualities)
+    {
+        $formula = $this->profit_formula($mchid);
+
+        if($formula === 'all')
+        {
+            $matcher = new whole_match($this,$this->mGrossRatios,$this->mTypeRatios,$this->mDetailRatios);
+            return $matcher->match($mchid, $org_quality, $card_type, $spec, $qualities);
+        }
+        elseif($formula === 'qt') {
+            $matcher = new type_match($this,$this->mGrossRatios,$this->mTypeRatios,$this->mDetailRatios);
+            return $matcher->match($mchid, $org_quality, $card_type, $spec, $qualities);
+        }
+        else {
+            $matcher = new type_spec_match($this,$this->mGrossRatios,$this->mTypeRatios,$this->mDetailRatios);
+            return $matcher->match($mchid, $org_quality, $card_type, $spec, $qualities);
+        }
+    }
+}

+ 74 - 0
helper/refill/policy/match/mixed_match.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace refill;
+
+abstract class mixed_match
+{
+    const delta = 0.0000001;
+
+    protected $mParent = null;
+
+    private $mGrossRatios;
+    private $mTypeRatios;
+    private $mDetailRatios;
+
+    public function __construct($parent, $gross, $types, $details)
+    {
+        $this->mParent = $parent;
+        $this->mGrossRatios = $gross;
+        $this->mTypeRatios = $types;
+        $this->mDetailRatios = $details;
+    }
+
+    //[submit_count, $succ_count, $fail_count, $succ_ratio, $profit, $profit_ratio]
+    protected function gross_ratio($mchid)
+    {
+        $mratios = $this->mGrossRatios;
+        if (array_key_exists($mchid, $mratios)) {
+            return $mratios[$mchid];
+        }
+
+        return [0, 0, 0, 0, 0, 0];
+    }
+
+    //[submit_count, $succ_count, $fail_count, $succ_ratio, $profit, $profit_ratio]
+    protected function types_ratio($mchid,$card_type)
+    {
+        $key = "{$mchid}-{$card_type}";
+        if (array_key_exists($key, $this->mTypeRatios)) {
+            return $this->mTypeRatios[$key];
+        }
+
+        return [0, 0, 0, 0, 0, 0];
+    }
+
+    //[submit_count, $succ_count, $fail_count, $succ_ratio, $profit, $profit_ratio]
+    protected function detail_ratio($mchid, $card_type, $spec)
+    {
+        $key = "{$mchid}-{$card_type}-{$spec}";
+        if (array_key_exists($key, $this->mDetailRatios)) {
+            return $this->mDetailRatios[$key];
+        }
+
+        return [0, 0, 0, 0, 0, 0];
+    }
+
+    protected function max_pre_rate($lowest_ratio)
+    {
+        if ($lowest_ratio >= 0.95) {
+            $max_ratio = 1.0;
+        }
+        elseif($lowest_ratio >= 0.90) {
+            $max_ratio = 1.02;
+        }
+        elseif ($lowest_ratio >= 0.5) {
+            $max_ratio = 1.05;
+        }
+        else {
+            $max_ratio = 1.07;
+        }
+        return $max_ratio;
+    }
+
+    abstract public function match($mchid, $org_quality, $card_type, $spec, $qualities);
+}

+ 185 - 0
helper/refill/policy/match/type_match.php

@@ -0,0 +1,185 @@
+<?php
+
+namespace refill;
+use Log;
+
+
+class type_match extends mixed_match
+{
+    //match: true 表示当前质量满足条件,可以不走溢价,false,表示可以走溢价
+    //can_last: true,能补充,false 表示不能走溢价
+    public function match($mchid, $org_quality, $card_type, $spec, $qualities)
+    {
+        $pParent = $this->mParent;
+
+        $lowest_ratio   = $pParent->lowest_ratio($mchid);
+        $lowest_pratio  = $pParent->profit_ratio($mchid);
+
+        $header = __METHOD__ . " mchid={$mchid} card_type={$card_type} spec={$spec}";
+        [$submit_count, $succ_count, $fail_count, $type_ratio, $profit, $type_pratio] = $this->types_ratio($mchid, $card_type);
+        Log::record("{$header} lowest_ratio={$lowest_ratio} lowest_pratio={$lowest_pratio} type_ratio={$type_ratio}, type_pratio={$type_pratio}", Log::DEBUG);
+
+        if ($type_pratio > $lowest_pratio) {
+            $can_last = true;
+        } else {
+            $can_last = false;
+        }
+
+        if (!PolicyUtil::mixed_quality($org_quality)) {
+            if ($type_ratio >= $lowest_ratio) {
+                return [true, true];
+            } else {
+                return [false, true];
+            }
+        } elseif ($type_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);
+            return [$match, $can_last];
+        }
+    }
+
+    private function pre_checker($mchid, $card_type, $spec, $header, $lowest_ratio)
+    {
+        $pParent = $this->mParent;
+
+        //计算各个card_type,spec 提交订单的占比情况,及所有面额
+        $spec_ratios = function ($mchid, $type_specs, $all_submit)
+        {
+            $specs = [];
+            $spec_details = [];
+            foreach ($type_specs as $item)
+            {
+                [$card_type, $spec] = $item;
+                if(!array_key_exists($spec,$spec_details)) {
+                    $spec_details[$spec] = [];
+                    $specs[] = $spec;
+                }
+
+                [$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];
+            }
+
+            $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);
+
+                $ratios[$spec] = [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio];
+            }
+
+            return [$specs, $ratios];
+        };
+        $card_filter = function ($type_specs,$card_type)
+        {
+            $result = [];
+            foreach ($type_specs as $item)
+            {
+                [$_card_type, $_spec] = $item;
+                if($_card_type == $card_type) {
+                    $result[] = $item;
+                }
+            }
+
+            return $result;
+        };
+
+        $stat_succs = function ($specs,$spec_details)
+        {
+            $succs = 0;
+            foreach ($specs as $spec)
+            {
+                [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio] = $spec_details[$spec];
+                $succs += $succ_count;
+            }
+
+            return $succs;
+        };
+
+        $stat_commits = function ($specs,$spec_details)
+        {
+            $commits = 0;
+            foreach ($specs as $spec) {
+                [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio] = $spec_details[$spec];
+                $commits += $submit_count;
+            }
+
+            return $commits;
+        };
+
+
+        //找出最佳补充面额
+        $spec_filter = function ($all_submit, $specs, $spec_details, $lowest_ratio) use ($stat_succs, $stat_commits)
+        {
+            $count = count($specs);
+            if ($count <= 1 ) {
+                return [];
+            }
+
+            $must_succs = intval($all_submit * $lowest_ratio);
+            $count = count($specs);
+            for ($length = 1; $length < $count; $length++)
+            {
+                $low = array_slice($specs,0,$length);
+                $high = array_slice($specs,$length);
+
+                $commits = $stat_commits($low,$spec_details);
+                $succs = $stat_succs($high,$spec_details);
+
+                if($commits > $must_succs - $succs) {
+                    return $low;
+                }
+            }
+
+            return [];
+        };
+
+
+        $lowest_pratio = $pParent->profit_ratio($mchid);
+        [$all_submit, $succ_count, $fail_count, $type_ratio, $profit, $type_pratio] = $this->types_ratio($mchid,$card_type);
+
+        if ($type_pratio <= $lowest_pratio) {
+            return true;
+        }
+
+        $ratio = $type_ratio / ($lowest_ratio + self::delta);
+        $max_ratio = $this->max_pre_rate($lowest_ratio);
+
+        if($ratio >= $max_ratio) {
+            return true;
+        }
+        else
+        {
+            $type_specs = $pParent->type_specs($mchid);
+            $type_specs = $card_filter($type_specs, $card_type);
+            [$specs, $spec_details] = $spec_ratios($mchid, $type_specs, $all_submit);
+            sort($specs);
+
+            $meet = $spec_filter($all_submit, $specs, $spec_details, $lowest_ratio);
+            $exist = in_array($spec, $meet);
+            return !$exist;
+        }
+    }
+
+    private function all_checker($mchid, $card_type)
+    {
+        $pParent = $this->mParent;
+        $lowest_pratio = $pParent->profit_ratio($mchid);
+        [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $type_pratio] = $this->types_ratio($mchid,$card_type);
+        //当前毛利润率小于最低利润率的时候,不可以补充了
+        if ($type_pratio <= $lowest_pratio) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

+ 43 - 0
helper/refill/policy/match/type_spec_match.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace refill;
+use Log;
+
+
+class type_spec_match extends mixed_match
+{
+    //match: true 表示当前质量满足条件,可以不走溢价,false,表示可以走溢价
+    //can_last: true,能补充,false 表示不能走溢价
+    public function match($mchid, $org_quality, $card_type, $spec, $qualities)
+    {
+        $pParent = $this->mParent;
+
+        $lowest_ratio   = $pParent->lowest_ratio($mchid);
+        $lowest_pratio  = $pParent->profit_ratio($mchid);
+
+        $header = __METHOD__ . " mchid={$mchid} card_type={$card_type} spec={$spec}";
+        [$submit_count, $succ_count, $fail_count, $cur_ratio, $profit, $cur_pratio] = $this->detail_ratio($mchid, $card_type, $spec);
+        Log::record("{$header} lowest_ratio={$lowest_ratio} lowest_pratio={$lowest_pratio} detail_ratio={$cur_ratio}, detail_pratio={$cur_pratio}", Log::DEBUG);
+
+        if ($cur_pratio > $lowest_pratio) {
+            $can_last = true;
+        } else {
+            $can_last = false;
+        }
+
+        if (!PolicyUtil::mixed_quality($org_quality))
+        {
+            if ($cur_ratio >= $lowest_ratio) {
+                return [true, true];
+            } else {
+                return [false, true];
+            }
+        }
+        elseif ($cur_ratio >= $lowest_ratio) {
+            return [true, $can_last];
+        }
+        else {
+            return [false, $can_last];
+        }
+    }
+}

+ 173 - 0
helper/refill/policy/match/whole_match.php

@@ -0,0 +1,173 @@
+<?php
+
+namespace refill;
+use Log;
+
+
+class whole_match extends mixed_match
+{
+    //match: true 表示当前质量满足条件,可以不走溢价,false,表示可以走溢价
+    //can_last: true,能补充,false 表示不能走溢价
+    public function match($mchid, $org_quality, $card_type, $spec, $qualities)
+    {
+        $pParent = $this->mParent;
+
+        $lowest_ratio   = $pParent->lowest_ratio($mchid);
+        $lowest_pratio  = $pParent->profit_ratio($mchid);
+
+        $header = __METHOD__ . " mchid={$mchid} card_type={$card_type} spec={$spec}";
+        [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
+        Log::record("{$header} lowest_ratio={$lowest_ratio} lowest_pratio={$lowest_pratio} 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, $spec, $header, $lowest_ratio);
+            return [$match, $can_last];
+        } else {
+            $match = $this->all_checker($mchid);
+            return [$match, $can_last];
+        }
+    }
+
+    private function pre_checker($mchid, $spec, $header, $lowest_ratio)
+    {
+        $pParent = $this->mParent;
+
+        //计算各个card_type,spec 提交订单的占比情况,及所有面额
+        $spec_ratios = function ($mchid, $type_specs, $all_submit)
+        {
+            $specs = [];
+            $spec_details = [];
+            foreach ($type_specs as $item)
+            {
+                [$card_type, $spec] = $item;
+                if(!array_key_exists($spec,$spec_details)) {
+                    $spec_details[$spec] = [];
+                    $specs[] = $spec;
+                }
+
+                [$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];
+            }
+
+            $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);
+
+                $ratios[$spec] = [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio];
+            }
+
+            return [$specs, $ratios];
+        };
+
+        $stat_succs = function ($specs,$spec_details)
+        {
+            $succs = 0;
+            foreach ($specs as $spec)
+            {
+                [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio] = $spec_details[$spec];
+                $succs += $succ_count;
+            }
+
+            return $succs;
+        };
+
+        $stat_commits = function ($specs,$spec_details)
+        {
+            $commits = 0;
+            foreach ($specs as $spec) {
+                [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio] = $spec_details[$spec];
+                $commits += $submit_count;
+            }
+
+            return $commits;
+        };
+
+
+        //找出最佳补充面额
+        $spec_filter = function ($all_submit, $specs, $spec_details, $lowest_ratio) use ($stat_succs, $stat_commits)
+        {
+            $count = count($specs);
+            if ($count <= 1) {
+                return [];
+            }
+
+            $must_succs = intval($all_submit * $lowest_ratio);
+            $count = count($specs);
+            for ($length = 1; $length < $count; $length++)
+            {
+                $low = array_slice($specs,0,$length);
+                $high = array_slice($specs,$length);
+
+                $commits = $stat_commits($low,$spec_details);
+                $succs = $stat_succs($high,$spec_details);
+
+                if($commits > $must_succs - $succs) {
+                    return $low;
+                }
+            }
+
+            return [];
+        };
+
+
+        ################################################################################################################
+        $lowest_pratio = $pParent->profit_ratio($mchid);
+        [$all_submit, $succ_count, $fail_count, $gross_ratio, $profit, $cur_pratio] = $this->gross_ratio($mchid);
+
+        if ($cur_pratio <= $lowest_pratio) {
+            return true;
+        }
+
+        $rate = $gross_ratio / ($lowest_ratio + self::delta);
+        $max_rate = $this->max_pre_rate($lowest_ratio);
+
+        if($rate >= $max_rate) {
+            return true;
+        }
+        else
+        {
+            $type_specs = $pParent->type_specs($mchid);
+            [$specs, $spec_details] = $spec_ratios($mchid, $type_specs, $all_submit);
+            sort($specs);
+
+            $meet = $spec_filter($all_submit, $specs, $spec_details, $lowest_ratio);
+            $exist = in_array($spec, $meet);
+            return !$exist;
+        }
+    }
+
+    private function all_checker($mchid)
+    {
+        $pParent = $this->mParent;
+        $lowest_pratio = $pParent->profit_ratio($mchid);
+        [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
+        //当前毛利润率小于最低利润率的时候,不可以补充了
+        if ($gross_pratio <= $lowest_pratio) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

+ 24 - 186
helper/refill/policy/mratio_controlex.php

@@ -6,12 +6,11 @@ use Log;
 
 class mratio_controlex
 {
-    const delta = 0.0000001;
-
     private $mTimesConfig; //对应refill.ini 配置文件数据
     private $mInterceptConfig;
 
     private $mGrossRatios;
+    private $mTypeRatios;
     private $mDetailRatios;
 
     private $mMchQTS;
@@ -24,6 +23,7 @@ class mratio_controlex
         $this->mInterceptConfig = [];
 
         $this->mGrossRatios = [];
+        $this->mTypeRatios = [];
         $this->mDetailRatios = [];
 
         $this->mMixedPrices = [];
@@ -131,11 +131,14 @@ class mratio_controlex
         $this->mInterceptConfig = $mch_configs();
     }
 
-    public function update($gross_ratios, $detail_ratios)
+    public function update($gross_ratios, $detail_ratios,$type_ratios)
     {
         if (!empty($gross_ratios)) {
             $this->mGrossRatios = $gross_ratios;
         }
+        if (!empty($type_ratios)) {
+            $this->mTypeRatios = $type_ratios;
+        }
         if (!empty($detail_ratios)) {
             $this->mDetailRatios = $detail_ratios;
         }
@@ -215,11 +218,11 @@ class mratio_controlex
         }
     }
 
-    private function profit_formula($mchid) {
+    public function profit_formula($mchid) {
         return $this->mTimesConfig[$mchid]['profit_formula'] ?? 'qts';
     }
 
-    private function lowest_ratio($mchid)
+    public function lowest_ratio($mchid)
     {
         $lower_ratio = $this->mTimesConfig[$mchid]['lower_ratio'] ?? [];
         if (empty($lower_ratio)) {
@@ -229,215 +232,50 @@ class mratio_controlex
         }
     }
 
-    private function profit_ratio($mchid)
+    public function profit_ratio($mchid)
     {
         $profit_ratio = $this->mTimesConfig[$mchid]['profit_ratio'] ?? 0.0;
         return $profit_ratio;
     }
 
-    //[submit_count, $succ_count, $fail_count, $succ_ratio, $profit, $profit_ratio]
-    private function gross_ratio($mchid)
+    public function type_specs($mchid)
     {
-        $mratios = $this->mGrossRatios;
-        if (array_key_exists($mchid, $mratios)) {
-            return $mratios[$mchid];
+        if(array_key_exists($mchid,$this->mMchQTS)) {
+            return $this->mMchQTS[$mchid];
         }
-
-        return [0, 0, 0, 0, 0, 0];
-    }
-
-    //[submit_count, $succ_count, $fail_count, $succ_ratio, $profit, $profit_ratio]
-    private function detail_ratio($mchid, $card_type, $spec)
-    {
-        $key = "{$mchid}-{$card_type}-{$spec}";
-        if (array_key_exists($key, $this->mDetailRatios)) {
-            return $this->mDetailRatios[$key];
+        else {
+            return [];
         }
-
-        return [0, 0, 0, 0, 0, 0];
     }
 
     //match: true 表示当前质量满足条件,可以不走溢价,false,表示可以走溢价
     //can_last: true,能补充,false 表示不能走溢价
-    public function ratio_matchex($mchid, $org_quality, $card_type, $spec, $qualities)
+    public function ratio_match($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}";
-
-        Log::record("{$header} formula={$profit_formula}, lowest_ratio={$lowest_ratio} lowest_pratio={$lowest_pratio}", Log::DEBUG);
-
         $formula = $this->profit_formula($mchid);
-        Log::record("{$header} formula = {$formula}",Log::DEBUG);
+
+        $header = __METHOD__ . " mchid={$mchid} card_type={$card_type} spec={$spec}";
+        Log::record("{$header} formula={$formula}", Log::DEBUG);
 
         if($formula === 'all')
         {
-            [$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 {
-                $match = $this->all_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
-                return [$match,$can_last];
-            }
+            $matcher = new whole_match($this,$this->mGrossRatios,$this->mTypeRatios,$this->mDetailRatios);
+            return $matcher->match($mchid, $org_quality, $card_type, $spec, $qualities);
         }
         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)
-    {
-        //计算各个card_type,spec 提交订单的占比情况,及所有面额
-        $spec_ratios = function ($mchid, $type_specs, $all_submit)
-        {
-            $specs = [];
-            $spec_details = [];
-            foreach ($type_specs as $item)
-            {
-                [$card_type, $spec] = $item;
-                if(!in_array($spec,$spec_details)) {
-                    $spec_details[] = $spec;
-                    $specs[] = $spec;
-                }
-
-                [$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];
-            }
-
-            $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);
-
-                $ratios[$spec] = [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio];
-            }
-
-            return [$specs, $ratios];
-        };
-
-        $split_array
-
-        //找出最佳补充面额
-        $ts_filter = function ($all_submit, $specs, $spec_details, $ratio, $lowest_ratio)
-        {
-            $count = count($specs);
-            if ($count === 1) {
-                return true;
-            }
-
-
-            for ($i = 1; $i < $count; $i++)
-            {
-                end()
-
-            }
-
-            $mast_succs = intval($all_submit * $lowest_ratio);
-            $result = [];
-
-            $all = 0.00;
-            foreach ($spec_details as $item)
-            {
-                [$card_type, $spec, $submit_ratio, $cur_ratio, $cur_pratio] = $item;
-                $all += $submit_ratio * $cur_ratio;
-
-                $r = $all / ($lowest_ratio + self::delta);
-                if ($r > 1)
-                    break;
-                else {
-                    $result[] = "{$card_type}-{$spec}";
-                }
-            }
-            return $result;
-        };
-
-
-        $lowest_pratio = $this->profit_ratio($mchid);
-        [$all_submit, $succ_count, $fail_count, $gross_ratio, $profit, $cur_pratio] = $this->gross_ratio($mchid);
-
-        if ($cur_pratio <= $lowest_pratio) {
-            return true;
-        }
-
-        $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;
+            $matcher = new type_match($this,$this->mGrossRatios,$this->mTypeRatios,$this->mDetailRatios);
+            return $matcher->match($mchid, $org_quality, $card_type, $spec, $qualities);
         }
         else {
-            $max_ratio = 1.07;
-        }
-
-        if($ratio >= $max_ratio) {
-            return true;
-        }
-        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;
+            $matcher = new type_spec_match($this,$this->mGrossRatios,$this->mTypeRatios,$this->mDetailRatios);
+            return $matcher->match($mchid, $org_quality, $card_type, $spec, $qualities);
         }
     }
 
-    private function all_checker($mchid, $card_type, $spec, $header, $lowest_ratio)
-    {
-        $lowest_pratio = $this->profit_ratio($mchid);
-        [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
-        //当前毛利润率小于最低利润率的时候,不可以补充了
-        if ($gross_pratio <= $lowest_pratio) {
-            return true;
-        } else {
-            return false;
-        }
-    }
 
     //机构订单拦截
     public function need_intercept($mchid, $card_type, $card_state, $is_transfer, $card_no): bool

+ 2 - 2
helper/refill/policy/xyz/policy.php

@@ -618,9 +618,9 @@ class policy extends ProviderManager implements IPolicy
         return $this->mGlobalInterceptor->isIntercept($quality,$card_type,$region_no);
     }
 
-    public function update_mchratios($gross,$detail)
+    public function update_mchratios($gross,$detail,$types)
     {
-        $this->mRatioCtl->update($gross,$detail);
+        $this->mRatioCtl->update($gross,$detail,$types);
     }
 
     public function update_chctl($params)

+ 2 - 1
rdispatcher/codispatcher.php

@@ -91,8 +91,9 @@ function subscribe_message(&$quit, &$redis, $channels)
 
                         $gross = $counts['gross'];
                         $detail = $counts['detail'];
+                        $types = $counts['types'];
 
-                        refill\RefillFactory::instance()->UpdateMchRatios($gross,$detail);
+                        refill\RefillFactory::instance()->UpdateMchRatios($gross,$detail,$types);
                     }
                     elseif($type == 'channel_control') {
                         $ins = Cache::getInstance('cacheredis');

+ 1 - 6
test/TestError.php

@@ -59,10 +59,5 @@ class TestError extends PHPUnit_Framework_TestCase
         $y = urldecode($x);
     }
 
-    public function testSlice()
-    {
-        $a=array("red","green","blue","yellow","brown");
-        $x1 = array_slice($a,0,1);
-        $x2 = array_slice($a,1);
-    }
+
 }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 65 - 0
test/TestMixedMatch.php


+ 19 - 0
test/TestPHPLan.php

@@ -0,0 +1,19 @@
+<?php
+
+
+use PHPUnit\Framework\TestCase;
+
+class TestPHPLan extends TestCase
+{
+    public function testSlice()
+    {
+        $specs = ["red", "green", "blue", "yellow", "brown"];
+
+        $count = count($specs);
+        for ($length = 1; $length < $count; $length++)
+        {
+            $low = array_slice($specs,0,$length);
+            $high = array_slice($specs,$length);
+        }
+    }
+}