Skip to content

Commit 45badaa

Browse files
committed
re-write the pick_pair function
1 parent 420c340 commit 45badaa

File tree

1 file changed

+40
-71
lines changed

1 file changed

+40
-71
lines changed

app/services/user_vote_queue_matchup_service.rb

Lines changed: 40 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ def build!
7676
}
7777
end
7878
@projects_with_time.sort_by! { |p| p[:ship_date] }
79-
Rails.logger.info("projects_with_time: #{@projects_with_time.map { |p| [ p[:project_id], p[:votes_count] ] }}")
8079

8180
@unpaid_projects = @projects_with_time.select { |p| !p[:is_paid] }
8281
@paid_projects = @projects_with_time.select { |p| p[:is_paid] }
@@ -88,87 +87,57 @@ def build!
8887
def pick_pair(used_ship_event_ids: Set.new)
8988
return nil if @projects_with_time.size < 2
9089

91-
selected_project_data = []
9290
used_user_ids = Set.new
9391
used_repo_links = Set.new
9492

95-
attempts = 0
96-
max_attempts = 25
97-
while selected_project_data.size < 2 && attempts < max_attempts
98-
attempts += 1
99-
100-
if selected_project_data.empty?
101-
# First pick: unpaid and immature (< 12 votes) (kinda borrowing uncertaiity from bayseain systems but not really)
102-
available_unpaid_immature = @immature_unpaid_projects.select { |p| eligible_for_selection?(p, used_user_ids, used_repo_links, used_ship_event_ids) }
103-
available_unpaid_immature = @projects_with_time.select { |p| eligible_for_selection?(p, used_user_ids, used_repo_links, used_ship_event_ids) } if available_unpaid_immature.empty?
104-
# technically, it might be paid, but idc.
105-
first_project_data = weighted_sample(available_unpaid_immature)
106-
next unless first_project_data
107-
108-
selected_project_data << first_project_data
109-
used_user_ids << first_project_data[:user_id]
110-
used_repo_links << first_project_data[:repo_link] if first_project_data[:repo_link].present?
111-
112-
first_time = first_project_data[:total_time]
113-
min_time = first_time * 0.7
114-
max_time = first_time * 1.3
115-
116-
compatible_mature_unpaid = @mature_unpaid_projects.select { |p| eligible_for_selection?(p, used_user_ids, used_repo_links, used_ship_event_ids) && time_compatible?(p, min_time, max_time) }
117-
if compatible_mature_unpaid.any?
118-
second_project_data = weighted_sample(compatible_mature_unpaid)
119-
selected_project_data << second_project_data
120-
used_user_ids << second_project_data[:user_id]
121-
used_repo_links << second_project_data[:repo_link] if second_project_data[:repo_link].present?
122-
else
123-
compatible_paid = @paid_projects.select { |p| eligible_for_selection?(p, used_user_ids, used_repo_links, used_ship_event_ids) && time_compatible?(p, min_time, max_time) }
124-
if compatible_paid.any?
125-
second_project_data = weighted_sample(compatible_paid)
126-
selected_project_data << second_project_data
127-
used_user_ids << second_project_data[:user_id]
128-
used_repo_links << second_project_data[:repo_link] if second_project_data[:repo_link].present?
129-
else
130-
selected_project_data.clear
131-
used_user_ids.clear
132-
used_repo_links.clear
133-
end
134-
end
135-
end
93+
first_pool =
94+
@immature_unpaid_projects.presence ||
95+
@mature_unpaid_projects.presence ||
96+
@paid_projects.presence
97+
98+
first_candidates = first_pool.select { |p|
99+
eligible_for_selection?(p, used_user_ids, used_repo_links, used_ship_event_ids)
100+
}
101+
102+
first = weighted_sample(first_candidates)
103+
unless first
104+
Rails.logger.info("func pick_pair: can't find first project")
105+
return nil
136106
end
137107

138-
if selected_project_data.size < 2 && @unpaid_projects.any?
139-
eligible_unpaid = @unpaid_projects.reject { |p| used_ship_event_ids.include?(p[:ship_event_id]) }
140-
first_project_data = weighted_sample(eligible_unpaid)
141-
return nil unless first_project_data
142-
remaining_projects = @projects_with_time.reject { |p|
143-
p[:user_id] == first_project_data[:user_id] ||
144-
(p[:repo_link].present? && p[:repo_link] == first_project_data[:repo_link]) ||
145-
used_ship_event_ids.include?(p[:ship_event_id])
108+
used_user_ids << first[:user_id]
109+
used_repo_links << first[:repo_link]
110+
used_ship_event_ids = used_ship_event_ids.dup.add(first[:ship_event_id])
111+
112+
first_t = first[:total_time]
113+
min_t, max_t = [ first_t * 0.7, first_t * 1.3 ]
114+
115+
second_pool =
116+
@mature_unpaid_projects.presence ||
117+
@paid_projects.presence
118+
119+
second_candidates = second_pool.select { |p|
120+
eligible_for_selection?(p, used_user_ids, used_repo_links, used_ship_event_ids) && time_compatible?(p, min_t, max_t)
121+
}
122+
second = weighted_sample(second_candidates)
123+
124+
if second.nil?
125+
second_candidates = @projects_with_time.select { |p|
126+
eligible_for_selection?(p, used_user_ids, used_repo_links, used_ship_event_ids)
146127
}
147-
if remaining_projects.any?
148-
second_project_data = weighted_sample(remaining_projects)
149-
selected_project_data = [ first_project_data, second_project_data ]
150-
end
128+
second = weighted_sample(second_candidates)
151129
end
152130

153-
if selected_project_data.size < 2 && !@unpaid_projects.any?
154-
eligible_paid = @paid_projects.reject { |p| used_ship_event_ids.include?(p[:ship_event_id]) }
155-
eligible_paid = @projects_with_time.reject { |p| used_ship_event_ids.include?(p[:ship_event_id]) } if eligible_paid.empty?
156-
first_project_data = weighted_sample(eligible_paid)
157-
return nil unless first_project_data
158-
remaining_projects = @projects_with_time.reject { |p|
159-
p[:user_id] == first_project_data[:user_id] ||
160-
(p[:repo_link].present? && p[:repo_link] == first_project_data[:repo_link]) ||
161-
used_ship_event_ids.include?(p[:ship_event_id])
162-
}
163-
if remaining_projects.any?
164-
second_project_data = weighted_sample(remaining_projects)
165-
selected_project_data = [ first_project_data, second_project_data ]
166-
end
131+
unless second
132+
Rails.logger.info("func pick_pair: can't find second project")
133+
return nil
167134
end
168135

169-
return nil if selected_project_data.size < 2
136+
a = first[:ship_event_id]
137+
b = second[:ship_event_id]
138+
return nil if a.nil? || b.nil?
170139

171-
selected_project_data.map { |p| p[:ship_event_id] }.minmax
140+
[ a, b ].minmax
172141
end
173142

174143
private

0 commit comments

Comments
 (0)