Adapt discomfort calculator to use groups instead of affinity tags #79

Merged
bustikiller merged 2 commits from fix-hiearhy-load into main 2024-11-01 11:22:13 +00:00
3 changed files with 48 additions and 43 deletions
Showing only changes of commit d37dd44cd3 - Show all commits

View File

@ -14,23 +14,23 @@ class AffinityGroupsHierarchy < Array
end end
end end
def find(name) def find(id)
@references[name] @references[id]
end end
def <<(name) def <<(id)
new_node = Tree::TreeNode.new(name) new_node = Tree::TreeNode.new(id)
super(new_node).tap { @references[name] = new_node } super(new_node).tap { @references[id] = new_node }
end end
def register_child(parent_name, child_name) def register_child(parent_id, child_id)
@references[parent_name] << Tree::TreeNode.new(child_name).tap { |child_node| @references[child_name] = child_node } @references[parent_id] << Tree::TreeNode.new(child_id).tap { |child_node| @references[child_id] = child_node }
end end
def distance(name_a, name_b) def distance(id_a, id_b)
return nil if @references[name_a].nil? || @references[name_b].nil? 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 end
private private

View File

@ -14,7 +14,7 @@ module Tables
private private
def cohesion_penalty 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) distance = AffinityGroupsHierarchy.instance.distance(a, b)
next count_a * count_b if distance.nil? next count_a * count_b if distance.nil?

View File

@ -5,6 +5,11 @@ module Tables
RSpec.describe DiscomfortCalculator do RSpec.describe DiscomfortCalculator do
let(:calculator) { described_class.new(table) } 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 describe '#cohesion_penalty' do
before do before do
# Overridden in each test except trivial cases # 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) allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(group, group).and_return(0)
end end
allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('family', 'friends').and_return(nil) allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(family.id, friends.id).and_return(nil)
allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('friends', 'work').and_return(1) allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(friends.id, work.id).and_return(1)
allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('family', 'work').and_return(2) allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(family.id, work.id).and_return(2)
allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('family', 'school').and_return(3) allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(family.id, school.id).and_return(3)
allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('friends', 'school').and_return(4) allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(friends.id, school.id).and_return(4)
allow(AffinityGroupsHierarchy.instance).to receive(:distance).with('work', 'school').and_return(5) allow(AffinityGroupsHierarchy.instance).to receive(:distance).with(work.id, school.id).and_return(5)
end end
context 'when the table contains just two guests' do context 'when the table contains just two guests' do
context 'when they belong to the same group' 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) } it { expect(calculator.send(:cohesion_penalty)).to eq(0) }
end end
@ -31,8 +36,8 @@ module Tables
context 'when they belong to completely unrelated groups' do context 'when they belong to completely unrelated groups' do
let(:table) do let(:table) do
[ [
create(:guest, affinity_group_list: ['family']), create(:guest, group: family),
create(:guest, affinity_group_list: ['friends']) create(:guest, group: friends)
] ]
end end
it { expect(calculator.send(:cohesion_penalty)).to eq(1) } 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 context 'when they belong to groups at a distance of 1' do
let(:table) do let(:table) do
[ [
create(:guest, affinity_group_list: ['friends']), create(:guest, group: friends),
create(:guest, affinity_group_list: ['work']) create(:guest, group: work)
] ]
end end
@ -52,8 +57,8 @@ module Tables
context 'when they belong to groups at a distance of 2' do context 'when they belong to groups at a distance of 2' do
let(:table) do let(:table) do
[ [
create(:guest, affinity_group_list: ['family']), create(:guest, group: family),
create(:guest, affinity_group_list: ['work']) create(:guest, group: work)
] ]
end end
@ -63,8 +68,8 @@ module Tables
context 'when they belong to groups at a distance of 3' do context 'when they belong to groups at a distance of 3' do
let(:table) do let(:table) do
[ [
create(:guest, affinity_group_list: ['family']), create(:guest, group: family),
create(:guest, affinity_group_list: ['school']) create(:guest, group: school)
] ]
end end
@ -75,9 +80,9 @@ module Tables
context 'when the table contains three guests' do context 'when the table contains three guests' do
let(:table) do let(:table) do
[ [
create(:guest, affinity_group_list: ['family']), create(:guest, group: family),
create(:guest, affinity_group_list: ['friends']), create(:guest, group: friends),
create(:guest, affinity_group_list: ['work']) create(:guest, group: work)
] ]
end end
@ -89,10 +94,10 @@ module Tables
context 'when the table contains four guests of different groups' do context 'when the table contains four guests of different groups' do
let(:table) do let(:table) do
[ [
create(:guest, affinity_group_list: ['family']), create(:guest, group: family),
create(:guest, affinity_group_list: ['friends']), create(:guest, group: friends),
create(:guest, affinity_group_list: ['work']), create(:guest, group: work),
create(:guest, affinity_group_list: ['school']) create(:guest, group: school)
] ]
end end
@ -105,8 +110,8 @@ module Tables
context 'when the table contains four guests of two evenly split groups' do context 'when the table contains four guests of two evenly split groups' do
let(:table) do let(:table) do
[ [
create_list(:guest, 2, affinity_group_list: ['family']), create_list(:guest, 2, group: family),
create_list(:guest, 2, affinity_group_list: ['friends']) create_list(:guest, 2, group: friends)
].flatten ].flatten
end end
@ -118,8 +123,8 @@ module Tables
context 'when the table contains six guests of two unevenly split groups' do context 'when the table contains six guests of two unevenly split groups' do
let(:table) do let(:table) do
[ [
create_list(:guest, 2, affinity_group_list: ['family']), create_list(:guest, 2, group: family),
create_list(:guest, 4, affinity_group_list: ['friends']) create_list(:guest, 4, group: friends)
].flatten ].flatten
end end
@ -131,9 +136,9 @@ module Tables
context 'when the table contains six guests of three evenly split groups' do context 'when the table contains six guests of three evenly split groups' do
let(:table) do let(:table) do
[ [
create_list(:guest, 2, affinity_group_list: ['family']), create_list(:guest, 2, group: family),
create_list(:guest, 2, affinity_group_list: ['friends']), create_list(:guest, 2, group: friends),
create_list(:guest, 2, affinity_group_list: ['work']) create_list(:guest, 2, group: work)
].flatten ].flatten
end end
@ -145,9 +150,9 @@ module Tables
context 'when the table contains six guests of three unevenly split groups' do context 'when the table contains six guests of three unevenly split groups' do
let(:table) do let(:table) do
[ [
create_list(:guest, 3, affinity_group_list: ['family']), create_list(:guest, 3, group: family),
create_list(:guest, 2, affinity_group_list: ['friends']), create_list(:guest, 2, group: friends),
create_list(:guest, 1, affinity_group_list: ['work']) create_list(:guest, 1, group: work)
].flatten ].flatten
end end