Update - 1.7.0.89
EN: 1.7.0.89 CN: 1.7.0.91 JP: 1.7.0.92 KR: 1.7.0.95
This commit is contained in:
@@ -920,41 +920,6 @@ function DispatchCtrl:can_meet_requirements(role_tags, requirements)
|
||||
end
|
||||
return true
|
||||
end
|
||||
function DispatchCtrl:calculate_role_score(role_tags, normal_req, extra_req)
|
||||
local score = 0
|
||||
local tag_count = {}
|
||||
for _, tag in ipairs(role_tags) do
|
||||
tag_count[tag] = (tag_count[tag] or 0) + 1
|
||||
end
|
||||
for _, req in ipairs(normal_req) do
|
||||
if tag_count[req] and 0 < tag_count[req] then
|
||||
score = score + 10
|
||||
tag_count[req] = tag_count[req] - 1
|
||||
end
|
||||
end
|
||||
for _, req in ipairs(extra_req) do
|
||||
if tag_count[req] and 0 < tag_count[req] then
|
||||
score = score + 3
|
||||
tag_count[req] = tag_count[req] - 1
|
||||
end
|
||||
end
|
||||
return score
|
||||
end
|
||||
function DispatchCtrl:count_remaining_requirements(selected_tags, requirements)
|
||||
local tag_count = {}
|
||||
for _, tag in ipairs(selected_tags) do
|
||||
tag_count[tag] = (tag_count[tag] or 0) + 1
|
||||
end
|
||||
local remaining = {}
|
||||
for _, req in ipairs(requirements) do
|
||||
if not tag_count[req] or tag_count[req] <= 0 then
|
||||
table.insert(remaining, req)
|
||||
else
|
||||
tag_count[req] = tag_count[req] - 1
|
||||
end
|
||||
end
|
||||
return remaining
|
||||
end
|
||||
function DispatchCtrl:concat_tags(selected_roles)
|
||||
local combined_tags = {}
|
||||
for _, role in ipairs(selected_roles) do
|
||||
@@ -964,136 +929,61 @@ function DispatchCtrl:concat_tags(selected_roles)
|
||||
end
|
||||
return combined_tags
|
||||
end
|
||||
function DispatchCtrl:enumerate_combinations(roles, count, callback)
|
||||
local n = #roles
|
||||
if count > n then
|
||||
return nil
|
||||
end
|
||||
local indices = {}
|
||||
for i = 1, count do
|
||||
indices[i] = i
|
||||
end
|
||||
while true do
|
||||
local combo = {}
|
||||
for i = 1, count do
|
||||
combo[i] = roles[indices[i]]
|
||||
end
|
||||
if callback(combo) then
|
||||
return combo
|
||||
end
|
||||
local pos = count
|
||||
while 1 <= pos and indices[pos] == n - count + pos do
|
||||
pos = pos - 1
|
||||
end
|
||||
if pos < 1 then
|
||||
break
|
||||
end
|
||||
indices[pos] = indices[pos] + 1
|
||||
for i = pos + 1, count do
|
||||
indices[i] = indices[i - 1] + 1
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
function DispatchCtrl:find_min_roles_greedy(roles, normal_req, extra_req)
|
||||
if #roles == 0 then
|
||||
return nil
|
||||
end
|
||||
for target_count = 1, 3 do
|
||||
local result = self:greedy_select_roles_with_limit(roles, normal_req, extra_req, true, target_count)
|
||||
for count = 1, 3 do
|
||||
local result = self:enumerate_combinations(roles, count, function(combo)
|
||||
local tags = self:concat_tags(combo)
|
||||
return self:can_meet_requirements(tags, normal_req) and self:can_meet_requirements(tags, extra_req)
|
||||
end)
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
end
|
||||
for target_count = 1, 3 do
|
||||
local result = self:greedy_select_roles_with_limit(roles, normal_req, {}, false, target_count)
|
||||
for count = 1, 3 do
|
||||
local result = self:enumerate_combinations(roles, count, function(combo)
|
||||
local tags = self:concat_tags(combo)
|
||||
return self:can_meet_requirements(tags, normal_req)
|
||||
end)
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
function DispatchCtrl:greedy_select_roles_with_limit(roles, normal_req, extra_req, check_both, max_count)
|
||||
if #normal_req == 0 and #extra_req == 0 then
|
||||
return {}
|
||||
end
|
||||
local scored_roles = {}
|
||||
for _, role in ipairs(roles) do
|
||||
local score = self:calculate_role_score(role.tags, normal_req, extra_req)
|
||||
if 0 < score then
|
||||
table.insert(scored_roles, {role = role, score = score})
|
||||
end
|
||||
end
|
||||
if #scored_roles == 0 then
|
||||
return nil
|
||||
end
|
||||
table.sort(scored_roles, function(a, b)
|
||||
return a.score > b.score
|
||||
end)
|
||||
return self:try_combinations_greedy(scored_roles, normal_req, extra_req, check_both, max_count)
|
||||
end
|
||||
function DispatchCtrl:try_combinations_greedy(scored_roles, normal_req, extra_req, check_both, target_count)
|
||||
local max_attempts = math.min(100, #scored_roles * target_count)
|
||||
local attempt_count = 0
|
||||
local selected = {}
|
||||
local selected_tags = {}
|
||||
for _, scored_role in ipairs(scored_roles) do
|
||||
if target_count <= #selected then
|
||||
break
|
||||
end
|
||||
attempt_count = attempt_count + 1
|
||||
if max_attempts < attempt_count then
|
||||
break
|
||||
end
|
||||
local remaining_normal = self:count_remaining_requirements(selected_tags, normal_req)
|
||||
local remaining_extra = self:count_remaining_requirements(selected_tags, extra_req)
|
||||
if #remaining_normal == 0 and #remaining_extra == 0 then
|
||||
break
|
||||
end
|
||||
local can_help = DispatchCtrl.role_can_help(scored_role.role.tags, remaining_normal, remaining_extra)
|
||||
if can_help then
|
||||
table.insert(selected, scored_role.role)
|
||||
for _, tag in ipairs(scored_role.role.tags) do
|
||||
table.insert(selected_tags, tag)
|
||||
end
|
||||
end
|
||||
end
|
||||
if #selected == target_count then
|
||||
if check_both then
|
||||
if self:can_meet_requirements(selected_tags, normal_req) and self:can_meet_requirements(selected_tags, extra_req) then
|
||||
return selected
|
||||
end
|
||||
elseif self:can_meet_requirements(selected_tags, normal_req) then
|
||||
return selected
|
||||
end
|
||||
end
|
||||
if target_count <= 2 and target_count <= #scored_roles then
|
||||
for start_idx = 1, math.min(5, #scored_roles - target_count + 1) do
|
||||
attempt_count = attempt_count + 1
|
||||
if max_attempts < attempt_count then
|
||||
break
|
||||
end
|
||||
local test_selected = {}
|
||||
local test_tags = {}
|
||||
table.insert(test_selected, scored_roles[start_idx].role)
|
||||
for _, tag in ipairs(scored_roles[start_idx].role.tags) do
|
||||
table.insert(test_tags, tag)
|
||||
end
|
||||
for i = 1, #scored_roles do
|
||||
if target_count <= #test_selected then
|
||||
break
|
||||
end
|
||||
if i ~= start_idx then
|
||||
local remaining_normal = self:count_remaining_requirements(test_tags, normal_req)
|
||||
local remaining_extra = self:count_remaining_requirements(test_tags, extra_req)
|
||||
if #remaining_normal == 0 and #remaining_extra == 0 then
|
||||
break
|
||||
end
|
||||
if DispatchCtrl.role_can_help(scored_roles[i].role.tags, remaining_normal, remaining_extra) then
|
||||
table.insert(test_selected, scored_roles[i].role)
|
||||
for _, tag in ipairs(scored_roles[i].role.tags) do
|
||||
table.insert(test_tags, tag)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if #test_selected == target_count then
|
||||
if check_both then
|
||||
if self:can_meet_requirements(test_tags, normal_req) and self:can_meet_requirements(test_tags, extra_req) then
|
||||
return test_selected
|
||||
end
|
||||
elseif self:can_meet_requirements(test_tags, normal_req) then
|
||||
return test_selected
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
function DispatchCtrl.role_can_help(role_tags, remaining_normal, remaining_extra)
|
||||
for _, tag in ipairs(role_tags) do
|
||||
for _, req in ipairs(remaining_normal) do
|
||||
if tag == req then
|
||||
return true
|
||||
end
|
||||
end
|
||||
for _, req in ipairs(remaining_extra) do
|
||||
if tag == req then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
function DispatchCtrl:OnEvent_OpenBuildList(dispatchId)
|
||||
self.bOpenBuild = true
|
||||
self:RefreshSelectList(true, dispatchId)
|
||||
|
||||
Reference in New Issue
Block a user