diff --git a/app/controllers/admin/vp_controller.rb b/app/controllers/admin/vp_controller.rb
index f6865535..e08db947 100644
--- a/app/controllers/admin/vp_controller.rb
+++ b/app/controllers/admin/vp_controller.rb
@@ -1,8 +1,29 @@
include Process
+require 'json'
+require 'open3'
+
class Admin::VpController < Admin::AdminController
before_filter :authorize_vp
def index
end
+
+ def committees
+ @candidates = Candidate.approved.current.sort_by {|c| (c.person && c.person.last_name.downcase) || "zzz" }
+ cand_hash = {}
+ @committee_out = ""
+ @err = ""
+ @candidates.each{|cand| cand_hash[cand.person.id] = cand.committee_preferences}
+ Open3.popen3("python -i ../script/hungary") do |stdin, stdout, stderr|
+ input = JSON.dump(cand_hash)
+ stdin.puts "solve(split(parse('"+ input + "')))"
+ stdin.puts "exit()"
+ stdout.each_line { |line|
+ line.sub(/[0-9]{1,}/) {|num| Person.find_by_id(num.to_i).full_name}
+ @committee_out += "\n" + line}
+ stderr.each_line { |line| @err += "\n" + line}
+ stdin.close
+ end
+ end
end
diff --git a/app/views/admin/vp/committees.html.erb b/app/views/admin/vp/committees.html.erb
new file mode 100644
index 00000000..0886718d
--- /dev/null
+++ b/app/views/admin/vp/committees.html.erb
@@ -0,0 +1,4 @@
+Committee Assignments
+
+<%= simple_format(@err) %>
+<%= simple_format(@committee_out) %>
diff --git a/app/views/admin/vp/index.html.erb b/app/views/admin/vp/index.html.erb
index 8aad955a..49fb89e8 100644
--- a/app/views/admin/vp/index.html.erb
+++ b/app/views/admin/vp/index.html.erb
@@ -6,4 +6,5 @@
<%= link_to "Confirm RSVPs", confirm_rsvps_index_path('candidates') %>
Super Page
<%= link_to 'Cand Applications', admin_cand_applications_path %>
+ <%= link_to 'Committee Assigments', admin_vp_committees_path %>
diff --git a/config/routes.rb b/config/routes.rb
index 6f9bf6d7..0568afc5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -63,6 +63,7 @@
scope "vp" do
match "/" => "vp#index", :as => :vp, :via => [:get, :post]
+ get "committees" => "vp#committees", :as => :vp_committees
scope "eligibilities" do
get "/" => "eligibilities#list", :as => :eligibilities
post "update" => "eligibilities#update", :as => :update_eligibilities
diff --git a/script/hungary.py b/script/hungary.py
new file mode 100644
index 00000000..c49d89e8
--- /dev/null
+++ b/script/hungary.py
@@ -0,0 +1,45 @@
+import json
+from munkres import Munkres, print_matrix, make_cost_matrix
+
+def split(info):
+ committees = ['CompServ','Tutoring','Indrel','Activities','StudRel','Bridge','Service']
+ for cid in info['data']:
+ prefs = info['data'][cid]
+ for committee in committees:
+ start = prefs.find(committee)
+ prefs = prefs[:start] + committee + " " + prefs[start + len(committee):]
+ info['data'][cid] = prefs[:len(prefs)-1]
+ return info
+
+def parse(jsonInfo):
+ return json.loads(jsonInfo)
+
+#data format:
+#{data: {id: prefs...}, spots: {"compserv":3...}}
+def solve(info):
+ matrix = [] #'profit matrix'
+ #sorted list of all candidate ids
+ candidates = sorted([cid for cid in info['data']])
+ #map candidates to a list of their preferences
+ c_prefs = {cid:info['data'][cid].split(" ") for cid in info['data']}
+ length = len(c_prefs[0]) #number of choices
+ #sorted list of all committee spots
+ c_spots = sorted([name for name in info['spots']
+ for _ in range(info['spots'][name])])
+
+ #building the matrix, each represents a candidate
+ for cid in candidates:
+ prefs_matrix = []
+ for spot in c_spots:
+ #first in preference list given highest weight
+ prefs_matrix.append((length - c_prefs[cid].index(spot)))
+ matrix.append(prefs_matrix)
+
+ #turn 'profit matrix' into 'cost matrix' by subtracting from a
+ #sufficiently large ceiling, in this case: 100
+ cost_matrix = make_cost_matrix(matrix, lambda cost: 100 - cost)
+
+ m = Munkres()
+ indexes = m.compute(cost_matrix)
+ for row, column in indexes:
+ print('{0} : {1}'.format(row, c_spots[column]))
\ No newline at end of file