From 8c6974a1e56e462d53789ecbd1d804c304e2c24f Mon Sep 17 00:00:00 2001 From: Manuel Bustillo Date: Thu, 1 Aug 2024 18:43:56 +0200 Subject: [PATCH] Replace rule that calculates discomfort --- app/services/tables/discomfort_calculator.rb | 14 ++-- .../tables/discomfort_calculator_spec.rb | 64 +++++++++++-------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/app/services/tables/discomfort_calculator.rb b/app/services/tables/discomfort_calculator.rb index 3ba39e7..4a1f5c8 100644 --- a/app/services/tables/discomfort_calculator.rb +++ b/app/services/tables/discomfort_calculator.rb @@ -6,17 +6,19 @@ module Tables end def calculate - group_merging + cohesion_penalty end private - def group_merging - 10 * (number_of_groups - 1) - end + def cohesion_penalty + table.map { |guest| guest.affinity_group_list.first }.combination(2).sum do |a, b| + distance = AffinityGroupsHierarchy.instance.distance(a, b) + next 1 if distance.nil? + next 0 if distance.zero? - def number_of_groups - table.map(&:affinity_groups).flatten.uniq.count + Rational(distance, distance + 1) + end end end end diff --git a/spec/services/tables/discomfort_calculator_spec.rb b/spec/services/tables/discomfort_calculator_spec.rb index c997ac2..1e59103 100644 --- a/spec/services/tables/discomfort_calculator_spec.rb +++ b/spec/services/tables/discomfort_calculator_spec.rb @@ -1,42 +1,50 @@ require 'rails_helper' module Tables RSpec.describe DiscomfortCalculator do - describe '#group_merging' do - let(:calculator) { described_class.new(table) } - - context 'when there is just one group in the table' do + let(:calculator) { described_class.new(table) } + + describe '#cohesion_penalty' do + context 'when the table contains just two guests' do let(:table) do - create_list(:guest, 3).each do |guest| - guest.affinity_group_list.add('family') - guest.save! - end + [ + create(:guest, affinity_group_list: ['family']), + create(:guest, affinity_group_list: ['friends']) + ] end - it { expect(calculator.send(:group_merging)).to eq(0) } - end - - context 'when the table contains two groups' do - let(:table) do - guests = create_list(:guest, 3) - guests[0].affinity_group_list.add('family') - guests[1].affinity_group_list.add('friends') - guests[2].affinity_group_list.add('family') - guests.each(&:save!) + before do + allow(AffinityGroupsHierarchy.instance).to receive(:distance).and_return(distance) end - it { expect(calculator.send(:group_merging)).to eq(10) } - end + context 'when they belong to the same group' do + let(:distance) { 0 } - context 'when the table contains three groups' do - let(:table) do - guests = create_list(:guest, 3) - guests[0].affinity_group_list.add('family') - guests[1].affinity_group_list.add('friends') - guests[2].affinity_group_list.add('work') - guests.each(&:save!) + it { expect(calculator.send(:cohesion_penalty)).to eq(0) } end - it { expect(calculator.send(:group_merging)).to eq(20) } + context 'when they belong to completely unrelated groups' do + let(:distance) { nil } + + it { expect(calculator.send(:cohesion_penalty)).to eq(1) } + end + + context 'when they belong to groups at a distance of 1' do + let(:distance) { 1 } + + it { expect(calculator.send(:cohesion_penalty)).to eq(0.5) } + end + + context 'when they belong to groups at a distance of 2' do + let(:distance) { 2 } + + it { expect(calculator.send(:cohesion_penalty)).to eq(Rational(2, 3)) } + end + + context 'when they belong to groups at a distance of 3' do + let(:distance) { 3 } + + it { expect(calculator.send(:cohesion_penalty)).to eq(Rational(3, 4)) } + end end end end