mCtlItems = []; } public function add($ctls) { foreach ($ctls as $item) { $name = $item->name(); $max_speed = $item->max_speed(); if($max_speed > 0) { $this->mCtlItems[$name] = $item; } } } public function assign() { $pCtlItems = $this->mCtlItems; if(empty($pCtlItems)) return []; $namesor = function ($ctls) { $result = []; foreach ($ctls as $item) { $result[] = $item->name(); } return $result; }; $ctlsor = function ($names) use ($pCtlItems) { $result = []; foreach ($names as $name) { $result[] = $pCtlItems[$name]; } return $result; }; $elector = function ($none_names) use ($pCtlItems) { $sections = []; $total = 0; foreach ($none_names as $name) { $ctl_item = $pCtlItems[$name]; $length = $ctl_item->max_speed(); $total += $length; $sections[] = ['name' => $name,'length' => $length]; } $anchor = mt_rand(1,$total); foreach ($sections as $section) { $name = $section['name']; $length = $section['length']; if($anchor > $length) { $anchor -= $length; } else { return $name; } } }; $using_names = []; $all_names = $namesor($this->mCtlItems); do { $none_assign = array_diff($all_names,$using_names); if(count($none_assign) <= 1) { $using_names = array_merge($using_names,$none_assign); break; } else { $hit_name = $elector($none_assign); $using_names[] = $hit_name; } } while(true); Log::record("overload_assigner result= ". implode(',',$using_names),Log::DEBUG); return $ctlsor($using_names); } }