chctlex.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <?php
  2. namespace refill;
  3. use Log;
  4. use mtopcard;
  5. use algorithm;
  6. use scope_trace;
  7. class chctlex
  8. {
  9. protected $mSpeedtable;
  10. protected $mNameMapQuality;
  11. static $cache_names = [
  12. ['quality'=> 1,'name' => 'channel-ctl-oil-common-limit'],
  13. ['quality'=> 2,'name' => 'channel-ctl-oil-fast-limit'],
  14. ['quality'=> 3,'name' => 'channel-ctl-oil-card-limit'],
  15. ['quality'=> 5,'name' => 'channel-ctl-oil-slow-limit'],
  16. ['quality'=> 1,'name' => 'channel-ctl-phone-common-limit'],
  17. ['quality'=> 2,'name' => 'channel-ctl-phone-fast-limit'],
  18. ['quality'=> 3,'name' => 'channel-ctl-phone-card-limit'],
  19. ['quality'=> 4,'name' => 'channel-ctl-phone-third-limit'],
  20. ['quality'=> 5,'name' => 'channel-ctl-phone-slow-limit'], //24 hour
  21. ['quality'=> 6,'name' => 'channel-ctl-phone-slow6-limit'], //6 hour
  22. ['quality'=> 7,'name' => 'channel-ctl-phone-slow2-limit'], //2 hour
  23. ['quality'=> 8,'name' => 'channel-ctl-phone-slow48-limit'],//48 hour
  24. ['quality'=> 9,'name' => 'channel-ctl-phone-slow72-limit'] //72 hour
  25. ];
  26. public function __construct()
  27. {
  28. $this->mSpeedtable = [];
  29. }
  30. public function update_price($policy)
  31. {
  32. $QPTA = $policy->getQPTA();
  33. foreach ($this->mSpeedtable as $key => $item)
  34. {
  35. $quality = $item->quality();
  36. $name = $item->name();
  37. $spec = $item->spec();
  38. $card_type = $item->card_type();
  39. $prefix = "{$name}-{$card_type}-{$spec}";
  40. if(array_key_exists($quality,$QPTA) && array_key_exists($prefix,$QPTA[$quality])) {
  41. $price = $QPTA[$quality][$prefix]['price'];
  42. $item->set_price($price);
  43. }
  44. }
  45. }
  46. public function load($opened_names)
  47. {
  48. $this->mSpeedtable = [];
  49. $this->mNameMapQuality = [];
  50. foreach (self::$cache_names as $cache)
  51. {
  52. $quality = $cache['quality'];
  53. $cache_name = $cache['name'];
  54. $data = rcache($cache_name,"provider-");
  55. $data = unserialize($data['data']);
  56. $cfgs = empty($data) ? [] : $data;
  57. foreach ($cfgs as $items)
  58. {
  59. foreach ($items as $item)
  60. {
  61. $name = $item['name'];
  62. if(!algorithm::binary_search($opened_names,$name)) {
  63. continue;
  64. }
  65. $amount = $item['amount'];
  66. $card_type = $item['type'];
  67. $opened = $item['opened'] == 1;
  68. $sort = $item['sort'];
  69. $speed = $item['speed'];
  70. if($opened == false) continue;
  71. $key = $this->prefix($name,$amount,$card_type,$quality);
  72. $this->mSpeedtable[$key] = new ctl_itemex($name,$card_type,$amount,$speed,$sort,0,$opened,$quality);
  73. $this->mNameMapQuality["{$name}-{$card_type}-{$amount}"] = $quality;
  74. }
  75. }
  76. }
  77. }
  78. public function update_chctl($params)
  79. {
  80. foreach ($params as $key => $val)
  81. {
  82. [$name, $spec, $card_type] = explode('-', $key);
  83. $quality = $this->mNameMapQuality["{$name}-{$card_type}-{$spec}"] ?? 0;
  84. if($quality <=0) continue;
  85. $prefix = $this->prefix($name,$spec,$card_type,$quality);
  86. $ctl = $this->mSpeedtable[$prefix] ?? null;
  87. if(is_null($ctl)) continue;
  88. $ctl->update_params($val);
  89. }
  90. }
  91. public function update_maxspeeds($params)
  92. {
  93. foreach ($params as $key => $val)
  94. {
  95. [$name, $spec, $card_type] = explode('-', $key);
  96. $quality = $this->mNameMapQuality["{$name}-{$card_type}-{$spec}"] ?? 0;
  97. if ($quality <= 0) continue;
  98. $prefix = $this->prefix($name,$spec,$card_type,$quality);
  99. $ctl = $this->mSpeedtable[$prefix] ?? null;
  100. if(is_null($ctl)) continue;
  101. Log::record("update_maxspeeds {$key} speed={$val}",Log::DEBUG);
  102. $ctl->update_maxspeeds($val);
  103. }
  104. }
  105. public function match($names, int $spec, int $card_type, int $quality, $max_inprice)
  106. {
  107. $trace = new scope_trace(__METHOD__);
  108. if ($card_type == mtopcard\ThirdRefillCard) {
  109. return $names;
  110. }
  111. $pThis = $this;
  112. $price_filter = function ($names, $spec, $card_type, $quality) use ($pThis, $max_inprice)
  113. {
  114. $ctls = [];
  115. foreach ($names as $name)
  116. {
  117. $key = $pThis->prefix($name,$spec,$card_type,$quality);
  118. if(array_key_exists($key,$pThis->mSpeedtable))
  119. {
  120. $item = $pThis->mSpeedtable[$key];
  121. $inPrice = $item->price();
  122. if ($max_inprice !== false && $inPrice > $max_inprice) {
  123. continue;
  124. } else {
  125. $ctls[] = $item;
  126. }
  127. }
  128. }
  129. return $ctls;
  130. };
  131. $ctl_items = $price_filter($names,$spec,$card_type,$quality);
  132. $chooser = function ($ctl_items)
  133. {
  134. $usable_items = [];
  135. foreach ($ctl_items as $item)
  136. {
  137. if($item->opened()) {
  138. $usable_items[] = $item;
  139. }
  140. }
  141. return $usable_items;
  142. };
  143. //去掉已经关闭通道
  144. $usable_items = $chooser($ctl_items);
  145. //不过载的排在前面
  146. $ascending = function ($l, $r)
  147. {
  148. $lproity = $l->priority();
  149. $rproity = $r->priority();
  150. $lover = $l->speed_overload() ? 1 : 0;
  151. $rover = $r->speed_overload() ? 1 : 0;
  152. if($lover == $rover)
  153. {
  154. if ($lover) {
  155. return $lproity > $rproity ? -1 : 1; //如果都过载保优先级高的
  156. } else {
  157. return $lproity < $rproity ? -1 : 1;
  158. }
  159. }
  160. else {
  161. return $lover < $rover ? -1 : 1;
  162. }
  163. };
  164. usort($usable_items, $ascending);
  165. $result = [];
  166. $over_loads = [];
  167. foreach ($usable_items as $item)
  168. {
  169. $name = $item->name();
  170. $over_load = $item->speed_overload();
  171. if($over_load) {
  172. $over_loads[] = $name;
  173. } else {
  174. $result[] = $name;
  175. }
  176. }
  177. $result = array_merge($result, $over_loads);
  178. return $result;
  179. }
  180. private function prefix($name,$spec,$card_type,$quality)
  181. {
  182. return "{$name}-{$spec}-{$card_type}-{$quality}";
  183. }
  184. public function auto_match($names, int $spec, int $card_type, int $quality, $out_price, $max_inprice, $left_time): array
  185. {
  186. $desc_profit = function ($l, $r) use($out_price)
  187. {
  188. $lProfit = $out_price - $l->price();
  189. $rProfit = $out_price - $r->price();
  190. $lVal = $l->compile_val($lProfit);
  191. $rVal = $r->compile_val($rProfit);
  192. Log::record("auto_match desc_profit lname={$l->name()} lval={$lVal} rname={$r->name()} rval={$rVal}",Log::DEBUG);
  193. if ($lVal == $rVal)
  194. {
  195. if($lVal == 0.0)
  196. {
  197. $lSubmits = $l->submits();
  198. $rSubmits = $r->submits();
  199. if($lSubmits > $rSubmits) {
  200. return 1;
  201. }
  202. elseif ($lSubmits < $rSubmits) {
  203. return -1;
  204. }
  205. else {
  206. return 0;
  207. }
  208. }
  209. elseif ($lProfit > $rProfit) {
  210. return -1;
  211. }
  212. elseif ($lProfit < $rProfit) {
  213. return 1;
  214. }
  215. else {
  216. return 0;
  217. }
  218. }
  219. elseif ($lVal > $rVal) {
  220. return -1;
  221. }
  222. else {
  223. return 1;
  224. }
  225. };
  226. $pThis = $this;
  227. $price_filter = function ($names,$spec,$card_type,$quality) use($pThis,$max_inprice)
  228. {
  229. $ctls = [];
  230. foreach ($names as $name)
  231. {
  232. $key = $pThis->prefix($name,$spec,$card_type,$quality);
  233. if(array_key_exists($key,$pThis->mSpeedtable))
  234. {
  235. $item = $pThis->mSpeedtable[$key];
  236. $inPrice = $item->price();
  237. //Log::record("key={$key} inPrice = {$inPrice} max_inprice = {$max_inprice}",Log::DEBUG);
  238. if ($max_inprice !== false && $inPrice > $max_inprice) {
  239. continue;
  240. } else {
  241. $ctls[] = $item;
  242. }
  243. }
  244. }
  245. return $ctls;
  246. };
  247. $ctl_splitor = function ($ctls)
  248. {
  249. $zeros = [];
  250. $workers = [];
  251. $overs = [];
  252. $stops = [];
  253. foreach ($ctls as $item)
  254. {
  255. Log::record("ctl_splitor {$item->name()} speed={$item->cur_speed()} max_speed={$item->max_speed()}",Log::DEBUG);
  256. if($item->zero_speed()) {
  257. $zeros[] = $item;
  258. }
  259. elseif($item->speed_stoped()) {
  260. $stops[] = $item;
  261. }
  262. elseif($item->speed_overload()) {
  263. $overs[] = $item;
  264. }
  265. else {
  266. $workers[] = $item;
  267. }
  268. }
  269. return [$zeros, $workers, $overs, $stops];
  270. };
  271. $time_map = function ($ctls, $left_time)
  272. {
  273. $header = [];
  274. $ender = [];
  275. foreach ($ctls as $item)
  276. {
  277. if($item->notify_time() <= $left_time + 600) {
  278. $header[] = $item;
  279. } else {
  280. $ender[] = $item;
  281. }
  282. }
  283. return array_merge($header,$ender);
  284. };
  285. $header_fun = function (int $spec, int $card_type, int $quality) {
  286. return "auto_match {$quality}-{$spec}-{$card_type}";
  287. };
  288. $header = $header_fun($spec,$card_type,$quality);
  289. $names_getter = function ($ctls) {
  290. $names = [];
  291. foreach ($ctls as $item) {
  292. $names[] = $item->name();
  293. }
  294. return $names;
  295. };
  296. $ctlitem_logger = function ($tag, $ctls) use ($header,$names_getter)
  297. {
  298. $result = [];
  299. foreach ($ctls as $item) {
  300. $result[] = "{$item->name()}: speed={$item->cur_speed()} max_speed={$item->max_speed()} notify={$item->notify_time()}";
  301. }
  302. $sname = implode(',', $result);
  303. Log::record("{$header} {$tag} :{$sname}",Log::DEBUG);
  304. };
  305. //end for log
  306. //working .....
  307. $names = array_unique($names);
  308. Log::record("auto_match outprice= {$out_price} max_inprice={$max_inprice} names=" . implode(',', $names), Log::DEBUG);
  309. $ctls = $price_filter($names, $spec, $card_type, $quality);
  310. $ctlitem_logger("price filter", $ctls);
  311. [$zeros, $workers, $overloads, $stops] = $ctl_splitor($ctls);
  312. $ctlitem_logger("zeros",$zeros);
  313. $ctlitem_logger("workers",$workers);
  314. $ctlitem_logger("overloads",$overloads);
  315. $ctlitem_logger("stops",$stops);
  316. usort($workers, $desc_profit);
  317. usort($overloads, $desc_profit);
  318. usort($stops, $desc_profit);
  319. $ctlitem_logger("sort workers",$workers);
  320. $ctlitem_logger("sort overloads",$overloads);
  321. $ctlitem_logger("sort stops",$stops);
  322. $ctls = array_merge($zeros, $workers, $overloads, $stops);
  323. $ctlitem_logger("result merge ctls", $ctls);
  324. $ctls = $time_map($ctls, $left_time);
  325. $ctlitem_logger("result time check ctls", $ctls);
  326. $names = $names_getter($ctls);
  327. return $names;
  328. }
  329. }