5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/type_balancer/distributor.rb', line 5
def self.calculate_target_positions(total_count:, ratio:, available_positions: nil)
return [] if total_count <= 0 || ratio <= 0 || ratio > 1
target_count = (total_count * ratio).ceil
if total_count == 3
target_count = if ratio <= 0.34
1
elsif ratio <= 0.67
2
else
3
end
end
return [] if target_count.zero?
return (0...total_count).to_a if target_count >= total_count
if available_positions
valid_positions = available_positions.select { |pos| pos >= 0 && pos < total_count }.sort
return [] if valid_positions.empty?
return [valid_positions.first] if target_count == 1
if target_count == 2
if total_count == 3
return [valid_positions[0], valid_positions[1]] if valid_positions.size >= 2
return [valid_positions.first, valid_positions.first + 1]
end
if available_positions.any? { |pos| pos >= total_count }
valid_positions = available_positions.select { |pos| pos >= 0 }.sort
return [valid_positions.first, valid_positions.last]
end
return [valid_positions.first, valid_positions.last]
end
return valid_positions if valid_positions.size <= target_count
return valid_positions.first(target_count) if target_count <= 3
target_positions = []
step = (valid_positions.size - 1).fdiv(target_count - 1)
(0...target_count).each do |i|
index = (i * step).round
target_positions << valid_positions[index]
end
target_positions
else
return [0] if target_count == 1
if target_count == 2
return [0, 1] if total_count == 3
return [0, total_count - 1]
end
(0...target_count).map do |i|
((total_count - 1) * i.fdiv(target_count - 1)).round
end
end
end
|