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 update_maxspeeds($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; Log::record("update_maxspeeds {$key} speed={$val}",Log::DEBUG); $ctl->update_maxspeeds($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[] = $name; } else { $result[] = $name; } } $result = array_merge($result, $over_loads); 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(); $rProfit = $out_price - $r->price(); $lVal = $l->compile_val($lProfit); $rVal = $r->compile_val($rProfit); Log::record("auto_match desc_profit lname={$l->name()} lval={$lVal} rname={$r->name()} rval={$rVal}",Log::DEBUG); if ($lVal == $rVal) { if($lVal == 0.0) { $lSubmits = $l->submits(); $rSubmits = $r->submits(); if($lSubmits > $rSubmits) { return 1; } elseif ($lSubmits < $rSubmits) { return -1; } else { return 0; } } elseif ($lProfit > $rProfit) { return -1; } elseif ($lProfit < $rProfit) { 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(); //Log::record("key={$key} inPrice = {$inPrice} max_inprice = {$max_inprice}",Log::DEBUG); if ($max_inprice !== false && $inPrice > $max_inprice) { continue; } else { $ctls[] = $item; } } } return $ctls; }; $ctl_splitor = function ($ctls) { $zeros = []; $workers = []; $overs = []; $stops = []; foreach ($ctls as $item) { Log::record("ctl_splitor {$item->name()} speed={$item->cur_speed()} max_speed={$item->max_speed()}",Log::DEBUG); if($item->zero_speed()) { $zeros[] = $item; } elseif($item->speed_stoped()) { $stops[] = $item; } elseif($item->speed_overload()) { $overs[] = $item; } else { $workers[] = $item; } } return [$zeros, $workers, $overs, $stops]; }; $time_map = function ($ctls, $left_time) { $header = []; $ender = []; foreach ($ctls as $item) { if($item->notify_time() <= $left_time + 600) { $header[] = $item; } else { $ender[] = $item; } } return array_merge($header,$ender); }; $header_fun = function (int $spec, int $card_type, int $quality) { return "auto_match {$quality}-{$spec}-{$card_type}"; }; $header = $header_fun($spec,$card_type,$quality); $names_getter = function ($ctls) { $names = []; foreach ($ctls as $item) { $names[] = $item->name(); } return $names; }; $ctlitem_logger = function ($tag, $ctls) use ($header,$names_getter) { $result = []; foreach ($ctls as $item) { $result[] = "{$item->name()}: speed={$item->cur_speed()} max_speed={$item->max_speed()} notify={$item->notify_time()}"; } $sname = implode(',', $result); Log::record("{$header} {$tag} :{$sname}",Log::DEBUG); }; //end for log //working ..... $names = array_unique($names); Log::record("auto_match outprice= {$out_price} max_inprice={$max_inprice} names=" . implode(',', $names), Log::DEBUG); $ctls = $price_filter($names, $spec, $card_type, $quality); $ctlitem_logger("price filter", $ctls); [$zeros, $workers, $overloads, $stops] = $ctl_splitor($ctls); $ctlitem_logger("zeros",$zeros); $ctlitem_logger("workers",$workers); $ctlitem_logger("overloads",$overloads); $ctlitem_logger("stops",$stops); usort($workers, $desc_profit); usort($overloads, $desc_profit); usort($stops, $desc_profit); $ctlitem_logger("sort workers",$workers); $ctlitem_logger("sort overloads",$overloads); $ctlitem_logger("sort stops",$stops); $ctls = array_merge($zeros, $workers, $overloads, $stops); $ctlitem_logger("result merge ctls", $ctls); $ctls = $time_map($ctls, $left_time); $ctlitem_logger("result time check ctls", $ctls); $names = $names_getter($ctls); return $names; } }