Преглед изворни кода

Merge branch 'rprofit' into raccex

stanley-king пре 2 година
родитељ
комит
5ade506ab0

+ 2 - 2
data/config/dev/base.ini.php

@@ -55,14 +55,14 @@ if(SSH_TUNEL_PROD ==='local') {
     $config['db'][1]['dbport']       = '3306';
     $config['db'][1]['dbuser']       = 'root';
     $config['db'][1]['dbpwd']        = '55668899';
-    $config['db'][1]['dbname']       = 'xyzshop';
+    $config['db'][1]['dbname']       = 'ylshop';
     $config['db'][1]['dbcharset']    = 'UTF-8';
 
     $config['db']['slave'][0]['dbhost']     = SLAVE_DBHOST;
     $config['db']['slave'][0]['dbport']     = '3306';
     $config['db']['slave'][0]['dbuser']     = 'root';
     $config['db']['slave'][0]['dbpwd']      = '55668899';
-    $config['db']['slave'][0]['dbname']     = 'xyzshop';
+    $config['db']['slave'][0]['dbname']     = 'ylshop';
     $config['db']['slave'][0]['dbcharset']  = 'UTF-8';
 }
 elseif(SSH_TUNEL_PROD === 'xyz') {

Разлика између датотеке није приказан због своје велике величине
+ 5378 - 258
data/config/dev/refill.ini.php


+ 11 - 5
helper/refill/RefillBase.php

@@ -452,7 +452,7 @@ class RefillBase
             $spec = $order->spec();
             $quality = $order->cur_quality();
 
-            [$state, $errmsg, $neterr] = $provider->add($card_no, $card_type, $spec, $params,$net_errno);
+            [$state, $errmsg, $neterr] = $provider->add($card_no, $card_type, $spec, $params, $net_errno);
             Log::record(sprintf(" %s add request time=%.6f: state={$state} neterr={$neterr},net_errno={$net_errno}", $channel_name,microtime(true) - $start), Log::DEBUG);
 
             if ($state)
@@ -886,14 +886,20 @@ class RefillBase
     {
         return $this->mPolicy->region_intercept($quality,$card_type,$region_no);
     }
+    public function UpdateMchRatios($gross,$detail)
+    {
+        $this->mPolicy->update_mchratios($gross,$detail);
+    }
 
-    public function UpdateRatio($ratios)
+    public function UpdateChctl($params)
     {
-        $this->mPolicy->update_ratios($ratios);
+        $this->mPolicy->update_chctl($params);
     }
-    public function UpdateMchRatios($gross,$detail)
+
+    //todo delete down lines
+    public function UpdateRatio($ratios)
     {
-        $this->mPolicy->update_mchratios($gross,$detail);
+        $this->mPolicy->update_ratios($ratios);
     }
     public function UpdateSpeeds($speeds)
     {

+ 2 - 0
helper/refill/XYZRefillFactory.php

@@ -14,7 +14,9 @@ require_once(BASE_HELPER_PATH . '/refill/policy/IPolicy.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/xyz/policy.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/try_judge.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/chctl.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/chctlex.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/ctl_item.php');
+require_once(BASE_HELPER_PATH . '/refill/policy/ctl_itemex.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/mchctl.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/mchoilctl.php');
 require_once(BASE_HELPER_PATH . '/refill/policy/times_caller.php');

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

@@ -19,4 +19,5 @@ interface IPolicy
     public function update_ratios($ratios);
     public function update_mchratios($all,$detail);
     public function update_chspeeds($speeds);
+    public function update_chctl($speeds);
 }

+ 375 - 0
helper/refill/policy/chctlex.php

@@ -0,0 +1,375 @@
+<?php
+
+
+namespace refill;
+
+use Log;
+use mtopcard;
+use algorithm;
+use scope_trace;
+
+class chctlex
+{
+    protected $mSpeedtable;
+    protected $mNameMapQuality;
+
+    static $cache_names = [
+        ['quality'=> 1,'name' => 'channel-ctl-oil-common-limit'],
+        ['quality'=> 2,'name' => 'channel-ctl-oil-fast-limit'],
+        ['quality'=> 3,'name' => 'channel-ctl-oil-card-limit'],
+        ['quality'=> 5,'name' => 'channel-ctl-oil-slow-limit'],
+
+        ['quality'=> 1,'name' => 'channel-ctl-phone-common-limit'],
+        ['quality'=> 2,'name' => 'channel-ctl-phone-fast-limit'],
+        ['quality'=> 3,'name' => 'channel-ctl-phone-card-limit'],
+        ['quality'=> 4,'name' => 'channel-ctl-phone-third-limit'],
+        ['quality'=> 5,'name' => 'channel-ctl-phone-slow-limit'],  //24 hour
+        ['quality'=> 6,'name' => 'channel-ctl-phone-slow6-limit'], //6 hour
+        ['quality'=> 7,'name' => 'channel-ctl-phone-slow2-limit'], //2 hour
+        ['quality'=> 8,'name' => 'channel-ctl-phone-slow48-limit'],//48 hour
+        ['quality'=> 9,'name' => 'channel-ctl-phone-slow72-limit'] //72 hour
+    ];
+
+    public function __construct()
+    {
+        $this->mSpeedtable = [];
+    }
+
+    public function update_price($policy)
+    {
+        $QPTA = $policy->getQPTA();
+        foreach ($this->mSpeedtable as $key => $item)
+        {
+            $quality = $item->quality();
+            $name = $item->name();
+            $spec = $item->spec();
+            $card_type = $item->card_type();
+
+            $prefix = "{$name}-{$card_type}-{$spec}";
+            if(array_key_exists($quality,$QPTA) && array_key_exists($prefix,$QPTA[$quality])) {
+                $price = $QPTA[$quality][$prefix]['price'];
+                $item->set_price($price);
+            }
+        }
+    }
+
+    public function load($opened_names)
+    {
+        $this->mSpeedtable = [];
+        $this->mNameMapQuality = [];
+        foreach (self::$cache_names as $cache)
+        {
+            $quality = $cache['quality'];
+            $cache_name = $cache['name'];
+            
+            $data = rcache($cache_name,"provider-");
+            $data = unserialize($data['data']);
+
+            $cfgs = empty($data) ? [] : $data;
+
+            foreach ($cfgs as $items)
+            {
+                foreach ($items as $item)
+                {
+                    $name = $item['name'];
+                    if(!algorithm::binary_search($opened_names,$name)) {
+                        continue;
+                    }
+
+                    $amount = $item['amount'];
+                    $card_type = $item['type'];
+
+                    $opened = $item['opened'] == 1;
+                    $sort = $item['sort'];
+                    $speed = $item['speed'];
+
+                    if($opened == false) continue;
+
+                    $key = $this->prefix($name,$amount,$card_type,$quality);
+                    $this->mSpeedtable[$key] = new ctl_itemex($name,$card_type,$amount,$speed,$sort,0,$opened,$quality);
+                    $this->mNameMapQuality["{$name}-{$card_type}-{$amount}"] = $quality;
+                }
+            }
+        }
+    }
+
+    public function update_chctl($params)
+    {
+        foreach ($params as $key => $val)
+        {
+            [$name, $spec, $card_type] = explode('-', $key);
+
+            $quality = $this->mNameMapQuality["{$name}-{$card_type}-{$spec}"] ?? 0;
+            if($quality <=0) continue;
+
+            $prefix = $this->prefix($name,$spec,$card_type,$quality);
+            $ctl = $this->mSpeedtable[$prefix] ?? null;
+            if(is_null($ctl)) continue;
+
+            $ctl->update_params($val);
+        }
+    }
+
+    //
+    public function match($names, int $spec, int $card_type, int $quality, $max_inprice)
+    {
+        $trace = new scope_trace(__METHOD__);
+        if ($card_type == mtopcard\ThirdRefillCard) {
+            return $names;
+        }
+
+        $pThis = $this;
+        $price_filter = function ($names,$spec,$card_type,$quality) use($pThis,$max_inprice)
+        {
+            $ctls = [];
+            foreach ($names as $name)
+            {
+                $key = $pThis->prefix($name,$spec,$card_type,$quality);
+                if(array_key_exists($key,$pThis->mSpeedtable))
+                {
+                    $item = $pThis->mSpeedtable[$key];
+
+                    $inPrice = $item->price();
+                    if ($max_inprice !== false && $inPrice > $max_inprice) {
+                        continue;
+                    } else {
+                        $ctls[] = $item;
+                    }
+                }
+            }
+            return $ctls;
+        };
+        $ctl_items = $price_filter($names,$spec,$card_type,$quality);
+
+        $chooser = function ($ctl_items)
+        {
+            $usable_items = [];
+            foreach ($ctl_items as $item)
+            {
+                if($item->opened()) {
+                    $usable_items[] = $item;
+                }
+            }
+
+            return $usable_items;
+        };
+
+        //去掉已经关闭通道
+        $usable_items = $chooser($ctl_items);
+
+        //不过载的排在前面
+        $ascending = function ($l, $r)
+        {
+            $lproity = $l->priority();
+            $rproity = $r->priority();
+
+            $lover = $l->speed_overload() ? 1 : 0;
+            $rover = $r->speed_overload() ? 1 : 0;
+
+            if($lover == $rover)
+            {
+                if ($lover) {
+                    return $lproity > $rproity ? -1 : 1; //如果都过载保优先级高的
+                } else {
+                    return $lproity < $rproity ? -1 : 1;
+                }
+            }
+            else {
+                return $lover < $rover ? -1 : 1;
+            }
+        };
+
+        usort($usable_items, $ascending);
+
+        $result = [];
+
+        $over_loads = [];
+        foreach ($usable_items as $item)
+        {
+            $name = $item->name();
+            $over_load = $item->speed_overload();
+            if($over_load) {
+                $over_loads[] = $item;
+            } else {
+                $result[] = $name;
+            }
+        }
+
+        if(!empty($over_loads))
+        {
+            $assigner = new overload_assigner();
+            $assigner->add($over_loads);
+            $over_loads = $assigner->assign();
+
+            foreach ($over_loads as $item) {
+                $result[] = $item->name();
+            }
+        }
+
+        return $result;
+    }
+
+    private function prefix($name,$spec,$card_type,$quality)
+    {
+        return "{$name}-{$spec}-{$card_type}-{$quality}";
+    }
+
+    public function auto_match($names, int $spec, int $card_type, int $quality, $out_price, $max_inprice, $left_time): array
+    {
+        $desc_profit = function ($l, $r) use($out_price)
+        {
+            $lProfit = $out_price - $l->price();
+            $rRrofit = $out_price - $r->price();
+
+            $lVal = $l->compile_val($lProfit);
+            $rVal = $r->compile_val($lProfit);
+
+            if ($lVal == $rVal)
+            {
+                if($lVal == 0.0)
+                {
+                    $lSubmits = $l->submits();
+                    $rSubmits = $r->submits();
+
+                    if($lSubmits > $rSubmits) {
+                        return 1;
+                    }
+                    elseif ($lProfit < $rRrofit) {
+                        return -1;
+                    }
+                    else {
+                        return 0;
+                    }
+                }
+                elseif ($lProfit > $rRrofit) {
+                    return -1;
+                }
+                elseif ($lProfit < $rRrofit) {
+                    return 1;
+                }
+                else {
+                    return 0;
+                }
+            }
+            elseif ($lVal > $rVal) {
+                return -1;
+            }
+            else {
+                return 1;
+            }
+        };
+
+
+        $pThis = $this;
+        $price_filter = function ($names,$spec,$card_type,$quality) use($pThis,$max_inprice)
+        {
+            $ctls = [];
+            foreach ($names as $name)
+            {
+                $key = $pThis->prefix($name,$spec,$card_type,$quality);
+                if(array_key_exists($key,$pThis->mSpeedtable))
+                {
+                    $item = $pThis->mSpeedtable[$key];
+                    $inPrice = $item->price();
+                    if ($max_inprice !== false && $inPrice > $max_inprice) {
+                        continue;
+                    } else {
+                        $ctls[] = $item;
+                    }
+                }
+                else {
+                    Log::record("auto_match speed table key={$key} is empty.",Log::DEBUG);
+                }
+            }
+            return $ctls;
+        };
+
+        $ctl_splitor = function ($ctls)
+        {
+            $feeds = [];
+            $workers = [];
+            $overs = [];
+
+            foreach ($ctls as $item)
+            {
+                if($item->need_feed()) {
+                    $feeds[] = $item;
+                }
+                elseif($item->speed_overload()) {
+                    $overs[] = $item;
+                }
+                else {
+                    $workers[] = $item;
+                }
+            }
+
+            return [$feeds,$workers,$overs];
+        };
+
+        $assign_feeds = function ($feeds)
+        {
+            if(empty($feeds)) {
+                return [[],[]];
+            }
+
+            $count = count($feeds);
+            $pos = mt_rand(0, $count * 60);
+
+            $cur_feeds = [];
+            $next_feeds = [];
+
+            $i = 0;
+            foreach ($feeds as $item)
+            {
+                if($i == $pos) {
+                    $cur_feeds[] = $item;
+                } else {
+                    $next_feeds[] = $item;
+                }
+            }
+
+            return [$cur_feeds,$next_feeds];
+        };
+
+        $time_map = function ($ctls, $left_time)
+        {
+            $header = [];
+            $ender = [];
+            foreach ($ctls as $item)
+            {
+                if($item->notify_time() > $left_time) {
+                    $header[] = $item;
+                } else {
+                    $ender[] = $item;
+                }
+            }
+
+            return array_merge($header,$ender);
+        };
+
+        $names = array_unique($names);
+        Log::record("auto_match outprice= {$out_price} names=" . implode(',', $names), Log::DEBUG);
+        $ctls = $price_filter($names,$spec,$card_type,$quality);
+        [$feeds,$workers,$overloads] = $ctl_splitor($ctls);
+
+        [$cur_feeds,$next_feeds] = $assign_feeds($feeds);
+        usort($workers, $desc_profit);
+
+        if(!empty($overloads)) {
+            $assigner = new overload_assigner();
+            $assigner->add($overloads);
+            $overloads = $assigner->assign();
+        }
+
+        $ctls = array_merge($cur_feeds, $workers, $overloads, $next_feeds);
+        $ctls = $time_map($ctls,$left_time);
+
+        $names = [];
+        foreach ($ctls as $item) {
+            $names[] = $item->name();
+        }
+
+        Log::record("auto_match result names=" . implode(',', $names), Log::DEBUG);
+        return $names;
+    }
+}

+ 141 - 0
helper/refill/policy/ctl_itemex.php

@@ -0,0 +1,141 @@
+<?php
+
+namespace refill;
+
+class ctl_itemex
+{
+    const feed_threshold = 10;
+
+    private $mName;
+    private $mCardType;
+    private $mAmount;
+    private $mQuality;
+
+    private $mMaxSpeed;
+    private $mPrefix;
+
+    private $mPriority;
+    private $mStorge;
+    private $mOpened;
+    private $mPrice;
+
+    private $mSpeed;
+    private $mRatio;
+    private $mRatioCommit;
+    private $mNotifyTime;
+    private $mMonitorCommit;
+
+
+    public function __construct($chname, $card_type, $amount, $max_speed, $priority, $storge, $opened, $quality)
+    {
+        $this->mPrefix = "{$chname}-{$quality}-{$card_type}-{$amount}";
+
+        $this->mName = $chname;
+        $this->mCardType = $card_type;
+        $this->mAmount = $amount;
+        $this->mQuality = $quality;
+
+        $this->mMaxSpeed = $max_speed;
+        $this->mPriority = $priority;
+        $this->mStorge = $storge;
+        $this->mOpened = $opened;
+        $this->mPrice = 0.0;
+
+        $this->mSpeed = 0;
+        $this->mRatio =0.0;
+        $this->mRatioCommit = 0;
+        $this->mNotifyTime = 0;
+        $this->mMonitorCommit = 0;
+    }
+
+    public function name()
+    {
+        return $this->mName;
+    }
+
+    public function priority()
+    {
+        return $this->mPriority;
+    }
+
+    public function storge()
+    {
+        return $this->mStorge;
+    }
+    public function opened()
+    {
+        return $this->mOpened;
+    }
+    public function quality()
+    {
+        return $this->mQuality;
+    }
+    public function spec()
+    {
+        return $this->mAmount;
+    }
+    public function card_type()
+    {
+        return $this->mCardType;
+    }
+    public function set_price($price)
+    {
+        $this->mPrice = $price;
+    }
+    public function price()
+    {
+        return $this->mPrice;
+    }
+    public function prefix() {
+        return $this->mPrefix;
+    }
+    public function update_params($parms)
+    {
+        [$this->mSpeed, $this->mRatio, $this->mRatioCommit, $this->mNotifyTime,$this->mMonitorCommit] = $parms;
+        if($this->mNotifyTime == 0) {
+            $this->mNotifyTime = 1;
+        }
+    }
+    public function max_speed()
+    {
+        return $this->mMaxSpeed;
+    }
+    public function speed_overload(): bool
+    {
+        if ($this->mMaxSpeed < 0) {
+            return false;
+        } elseif ($this->mMaxSpeed == 0) {
+            return true;
+        } else {
+            return $this->mSpeed >= $this->mMaxSpeed;
+        }
+    }
+
+    public function cur_speed()
+    {
+        return $this->mSpeed;
+    }
+    public function notify_ratio() {
+        return $this->mRatio;
+    }
+    public function submits() {
+        return $this->mRatioCommit;
+    }
+    public function notify_time() {
+        return $this->mNotifyTime;
+    }
+    public function need_feed()
+    {
+        if(self::feed_threshold >= $this->mMaxSpeed) {
+            return $this->mMonitorCommit == 0;
+        } else {
+            return $this->mMonitorCommit < self::feed_threshold;
+        }
+    }
+
+    public function compile_val($profit_ratio)
+    {
+        $val = $this->mRatio * $profit_ratio / $this->mNotifyTime;
+        return round($val,5);
+    }
+}

+ 6 - 1
helper/refill/policy/xyz/policy.php

@@ -24,7 +24,7 @@ class policy extends ProviderManager implements IPolicy
     public function __construct()
     {
         parent::__construct();
-        $this->mChannelControl = new chctl();
+        $this->mChannelControl = new chctlex();
         $this->mQuality = new quality_ploy();
         $this->mPrices = new merchant_price();
         $this->mStorageLocker = new rstorage();
@@ -627,8 +627,13 @@ class policy extends ProviderManager implements IPolicy
     {
         $this->mRatioCtl->update($gross,$detail);
     }
+
     public function update_chspeeds($speeds)
     {
         $this->mChannelControl->update_speeds($speeds);
     }
+    public function update_chctl($params)
+    {
+        $this->mChannelControl->update_chctl($params);
+    }
 }

+ 11 - 10
plot/refill/ChSpeedRatioCalc.py

@@ -14,7 +14,7 @@ class ChSpeedRatioCalc(ChannelCalc):
         logger.debug('_calc_handler')
 
         reader = self._reader()
-        end_time = int(time.time())
+        end_time = int(time.time() - 5 * 86400)
         period = 1800
         days, start_time, end_time = self.calc_time(reader, end_time - period, end_time)
 
@@ -22,20 +22,21 @@ class ChSpeedRatioCalc(ChannelCalc):
         tuple_pathes = reader.many_tuple_path(days, card_types=set([4, 5, 6]))
         gen = detail_pathes(reader, tuple_pathes, days)
 
-        speeds = dict()
         start_pos = start_time - day_stamp
         end_pos = end_time - day_stamp
+
+        result = dict()
         for _name, _card_type, _spec, _data in gen:
             speed = calc_chspeed(_data, pos_map, end_pos - 60, end_pos)
-            ratio, commit_count, bak_time = calc_chratio(_data, pos_map, end_pos - period, end_pos)
-            tenmin_commit = calc_commit(_data, pos_map, end_pos - 600, end_pos)
+            ratio, ratio_commit, notify_time = calc_chratio(_data, pos_map, end_pos - period, end_pos)
+            monitor_commit = calc_commit(_data, pos_map, end_pos - 300, end_pos)
 
             key = f'{_name}-{_spec}-{_card_type}'
-            speeds[key] = [speed, ratio, commit_count, bak_time,tenmin_commit]
-            logger.debug("%s-%d-%d speed=%d ratio=%.5f commit_count=%d bak_time=%.5f tenmin_commit=%d", _name, _card_type, _spec, speed, ratio,
-                         commit_count, bak_time, tenmin_commit)
+            result[key] = [speed, ratio, ratio_commit, notify_time, monitor_commit]
+            logger.debug("%s-%d-%d speed=%d ratio=%.5f commit_count=%d notify_time=%.5f monitor_commit=%d", _name, _card_type, _spec, speed, ratio,
+                         ratio_commit, notify_time, monitor_commit)
 
-        # if len(speeds) != 0:
-        #     rclient.set(f"nc_channel_speed_vsec", json.dumps(speeds))
-        #     rclient.publish('refill', json.dumps({'type': 'channel_speed', 'value': 0}))
+        if len(result) != 0:
+            rclient.set(f"nc_refill_channel_control_model", json.dumps(result))
+            rclient.publish('refill', json.dumps({'type': 'channel_control', 'value': 0}))
         return 0.1

+ 5 - 17
rdispatcher/codispatcher.php

@@ -81,18 +81,6 @@ function subscribe_message(&$quit, &$redis, $channels)
                         refill\RefillFactory::instance()->load();
                         refill\transfer::instance()->load();
                     }
-                    elseif($type == 'ratio') {
-                        $ins = Cache::getInstance('cacheredis');
-                        $val = $ins->get_org('channel_ratios');
-
-                        if(empty($val)) continue;
-                        $val = json_decode($val,true);
-                        if(empty($val)) continue;
-                        $ratios = $val['ratios'];
-                        if(empty($ratios)) continue;
-
-                        refill\RefillFactory::instance()->UpdateRatio($ratios);
-                    }
                     elseif($type == 'mch_profit_ratio') {
                         $ins = Cache::getInstance('cacheredis');
                         $content = $ins->get_org('refill_merchant_profit_ratio');
@@ -106,15 +94,15 @@ function subscribe_message(&$quit, &$redis, $channels)
 
                         refill\RefillFactory::instance()->UpdateMchRatios($gross,$detail);
                     }
-                    elseif($type == 'channels_speed') {
+                    elseif($type == 'channel_control') {
                         $ins = Cache::getInstance('cacheredis');
-                        $content = $ins->get_org('channels_speed');
+                        $content = $ins->get_org('refill_channel_control_model');
 
                         if(empty($content)) continue;
-                        $speeds = json_decode($content,true);
-                        if(empty($speeds)) continue;
+                        $params = json_decode($content,true);
+                        if(empty($params)) continue;
 
-                        refill\RefillFactory::instance()->UpdateSpeeds($speeds);
+                        refill\RefillFactory::instance()->UpdateChctl($params);
                     }
                     else {
                         //Log::record("subscribe_message dont not handle mgs:{$sub_type}-{$channel}-{$type}",Log::DEBUG);

+ 39 - 0
test/TestBigData.php

@@ -105,6 +105,45 @@ class TestBigData extends TestCase
 
         refill\RefillFactory::instance()->UpdateMchRatios($gross,$detail);
     }
+
+    public function testChannelContolModel()
+    {
+        $ins = Cache::getInstance('cacheredis');
+        $content = $ins->get_org('refill_channel_control_model');
+
+        $data = json_decode($content,true);
+        refill\RefillFactory::instance()->UpdateChctl($data);
+    }
+
+    public function testMtrand()
+    {
+        $feeds = [1, 2, 3, 4, 5];
+        $count = count($feeds);
+
+        $result = [];
+        for ($i = 0; $i < $count * 2; $i++) {
+            $val = mt_rand(0,$count);
+            $result[] = $val;
+        }
+
+        return $result;
+    }
+
+    public function testEqual()
+    {
+        $l = round(0.000000000009,10);
+        $r = round(0.000000000008,10);
+
+        if($l == $r)
+        {
+            if($l == 0.0) {
+                $i = 2;
+            }
+            else {
+                $i = 1;
+            }
+        }
+    }