From d37dd44cd39992fe85f2f7e03479151391f6f070 Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Fri, 1 Nov 2024 12:04:15 +0100 Subject: [PATCH] Update discomfort calculator to use group ids --- app/services/affinity_groups_hierarchy.rb | 20 +++--- app/services/tables/discomfort_calculator.rb | 2 +- .../tables/discomfort_calculator_spec.rb | 69 ++++++++++--------- 3 files changed, 48 insertions(+), 43 deletions(-) diff --git a/app/services/affinity_groups_hierarchy.rb b/app/services/affinity_groups_hierarchy.rb index 48db7fc..e20de97 100644 --- a/app/services/affinity_groups_hierarchy.rb +++ b/app/services/affinity_groups_hierarchy.rb @@ -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 diff --git a/app/services/tables/discomfort_calculator.rb b/app/services/tables/discomfort_calculator.rb index d6907e8..09b5356 100644 --- a/app/services/tables/discomfort_calculator.rb +++ b/app/services/tables/discomfort_calculator.rb @@ -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? diff --git a/spec/services/tables/discomfort_calculator_spec.rb b/spec/services/tables/discomfort_calculator_spec.rb index c2426ba..0e22602 100644 --- a/spec/services/tables/discomfort_calculator_spec.rb +++ b/spec/services/tables/discomfort_calculator_spec.rb @@ -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