Adapt discomfort calculator to use groups instead of affinity tags #79
| @ -14,23 +14,23 @@ class AffinityGroupsHierarchy < Array | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def find(name) | ||||
|     @references[name] | ||||
|   def find(id) | ||||
|     @references[id] | ||||
|   end | ||||
| 
 | ||||
|   def <<(name) | ||||
|     new_node = Tree::TreeNode.new(name) | ||||
|     super(new_node).tap { @references[name] = new_node } | ||||
|   def <<(id) | ||||
|     new_node = Tree::TreeNode.new(id) | ||||
|     super(new_node).tap { @references[id] = new_node } | ||||
|   end | ||||
| 
 | ||||
|   def register_child(parent_name, child_name) | ||||
|     @references[parent_name] << Tree::TreeNode.new(child_name).tap { |child_node| @references[child_name] = child_node } | ||||
|   def register_child(parent_id, child_id) | ||||
|     @references[parent_id] << Tree::TreeNode.new(child_id).tap { |child_node| @references[child_id] = child_node } | ||||
|   end | ||||
| 
 | ||||
|   def distance(name_a, name_b) | ||||
|     return nil if @references[name_a].nil? || @references[name_b].nil? | ||||
|   def distance(id_a, id_b) | ||||
|     return nil if @references[id_a].nil? || @references[id_b].nil? | ||||
| 
 | ||||
|     @references[name_a].distance_to_common_ancestor(@references[name_b]) | ||||
|     @references[id_a].distance_to_common_ancestor(@references[id_b]) | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
|  | ||||
| @ -14,7 +14,7 @@ module Tables | ||||
|     private | ||||
| 
 | ||||
|     def cohesion_penalty | ||||
|       table.map { |guest| guest.affinity_group_list.first }.tally.to_a.combination(2).sum do |(a, count_a), (b, count_b)| | ||||
|       table.map(&:group_id).tally.to_a.combination(2).sum do |(a, count_a), (b, count_b)| | ||||
|         distance = AffinityGroupsHierarchy.instance.distance(a, b) | ||||
| 
 | ||||
|         next count_a * count_b if distance.nil? | ||||
|  | ||||
| @ -5,6 +5,11 @@ module Tables | ||||
|   RSpec.describe DiscomfortCalculator do | ||||
|     let(:calculator) { described_class.new(table) } | ||||
| 
 | ||||
|     let(:family) { create(:group, name: 'family') } | ||||
|     let(:friends) { create(:group, name: 'friends') } | ||||
|     let(:work) { create(:group, name: 'work') } | ||||
|     let(:school) { create(:group, name: 'school') } | ||||
| 
 | ||||
|     describe '#cohesion_penalty' do | ||||
|       before do | ||||
|         # Overridden in each test except trivial cases | ||||
| @ -14,16 +19,16 @@ module Tables | ||||
|           allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(group, group).and_return(0) | ||||
|         end | ||||
| 
 | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('family', 'friends').and_return(nil) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('friends', 'work').and_return(1) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('family', 'work').and_return(2) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('family', 'school').and_return(3) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('friends', 'school').and_return(4) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('work', 'school').and_return(5) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(family.id, friends.id).and_return(nil) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(friends.id, work.id).and_return(1) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(family.id, work.id).and_return(2) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(family.id, school.id).and_return(3) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(friends.id, school.id).and_return(4) | ||||
|         allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(work.id, school.id).and_return(5) | ||||
|       end | ||||
|       context 'when the table contains just two guests' do | ||||
|         context 'when they belong to the same group' do | ||||
|           let(:table) { create_list(:guest, 2, affinity_group_list: ['family']) } | ||||
|           let(:table) { create_list(:guest, 2, group: family) } | ||||
| 
 | ||||
|           it { expect(calculator.send(:cohesion_penalty)).to eq(0) } | ||||
|         end | ||||
| @ -31,8 +36,8 @@ module Tables | ||||
|         context 'when they belong to completely unrelated groups' do | ||||
|           let(:table) do | ||||
|             [ | ||||
|               create(:guest, affinity_group_list: ['family']), | ||||
|               create(:guest, affinity_group_list: ['friends']) | ||||
|               create(:guest, group: family), | ||||
|               create(:guest, group: friends) | ||||
|             ] | ||||
|           end | ||||
|           it { expect(calculator.send(:cohesion_penalty)).to eq(1) } | ||||
| @ -41,8 +46,8 @@ module Tables | ||||
|         context 'when they belong to groups at a distance of 1' do | ||||
|           let(:table) do | ||||
|             [ | ||||
|               create(:guest, affinity_group_list: ['friends']), | ||||
|               create(:guest, affinity_group_list: ['work']) | ||||
|               create(:guest, group: friends), | ||||
|               create(:guest, group: work) | ||||
|             ] | ||||
|           end | ||||
| 
 | ||||
| @ -52,8 +57,8 @@ module Tables | ||||
|         context 'when they belong to groups at a distance of 2' do | ||||
|           let(:table) do | ||||
|             [ | ||||
|               create(:guest, affinity_group_list: ['family']), | ||||
|               create(:guest, affinity_group_list: ['work']) | ||||
|               create(:guest, group: family), | ||||
|               create(:guest, group: work) | ||||
|             ] | ||||
|           end | ||||
| 
 | ||||
| @ -63,8 +68,8 @@ module Tables | ||||
|         context 'when they belong to groups at a distance of 3' do | ||||
|           let(:table) do | ||||
|             [ | ||||
|               create(:guest, affinity_group_list: ['family']), | ||||
|               create(:guest, affinity_group_list: ['school']) | ||||
|               create(:guest, group: family), | ||||
|               create(:guest, group: school) | ||||
|             ] | ||||
|           end | ||||
| 
 | ||||
| @ -75,9 +80,9 @@ module Tables | ||||
|       context 'when the table contains three guests' do | ||||
|         let(:table) do | ||||
|           [ | ||||
|             create(:guest, affinity_group_list: ['family']), | ||||
|             create(:guest, affinity_group_list: ['friends']), | ||||
|             create(:guest, affinity_group_list: ['work']) | ||||
|             create(:guest, group: family), | ||||
|             create(:guest, group: friends), | ||||
|             create(:guest, group: work) | ||||
|           ] | ||||
|         end | ||||
| 
 | ||||
| @ -89,10 +94,10 @@ module Tables | ||||
|       context 'when the table contains four guests of different groups' do | ||||
|         let(:table) do | ||||
|           [ | ||||
|             create(:guest, affinity_group_list: ['family']), | ||||
|             create(:guest, affinity_group_list: ['friends']), | ||||
|             create(:guest, affinity_group_list: ['work']), | ||||
|             create(:guest, affinity_group_list: ['school']) | ||||
|             create(:guest, group: family), | ||||
|             create(:guest, group: friends), | ||||
|             create(:guest, group: work), | ||||
|             create(:guest, group: school) | ||||
|           ] | ||||
|         end | ||||
| 
 | ||||
| @ -105,8 +110,8 @@ module Tables | ||||
|       context 'when the table contains four guests of two evenly split groups' do | ||||
|         let(:table) do | ||||
|           [ | ||||
|             create_list(:guest, 2, affinity_group_list: ['family']), | ||||
|             create_list(:guest, 2, affinity_group_list: ['friends']) | ||||
|             create_list(:guest, 2, group: family), | ||||
|             create_list(:guest, 2, group: friends) | ||||
|           ].flatten | ||||
|         end | ||||
| 
 | ||||
| @ -118,8 +123,8 @@ module Tables | ||||
|       context 'when the table contains six guests of two unevenly split groups' do | ||||
|         let(:table) do | ||||
|           [ | ||||
|             create_list(:guest, 2, affinity_group_list: ['family']), | ||||
|             create_list(:guest, 4, affinity_group_list: ['friends']) | ||||
|             create_list(:guest, 2, group: family), | ||||
|             create_list(:guest, 4, group: friends) | ||||
|           ].flatten | ||||
|         end | ||||
| 
 | ||||
| @ -131,9 +136,9 @@ module Tables | ||||
|       context 'when the table contains six guests of three evenly split groups' do | ||||
|         let(:table) do | ||||
|           [ | ||||
|             create_list(:guest, 2, affinity_group_list: ['family']), | ||||
|             create_list(:guest, 2, affinity_group_list: ['friends']), | ||||
|             create_list(:guest, 2, affinity_group_list: ['work']) | ||||
|             create_list(:guest, 2, group: family), | ||||
|             create_list(:guest, 2, group: friends), | ||||
|             create_list(:guest, 2, group: work) | ||||
|           ].flatten | ||||
|         end | ||||
| 
 | ||||
| @ -145,9 +150,9 @@ module Tables | ||||
|       context 'when the table contains six guests of three unevenly split groups' do | ||||
|         let(:table) do | ||||
|           [ | ||||
|             create_list(:guest, 3, affinity_group_list: ['family']), | ||||
|             create_list(:guest, 2, affinity_group_list: ['friends']), | ||||
|             create_list(:guest, 1, affinity_group_list: ['work']) | ||||
|             create_list(:guest, 3, group: family), | ||||
|             create_list(:guest, 2, group: friends), | ||||
|             create_list(:guest, 1, group: work) | ||||
|           ].flatten | ||||
|         end | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user