2025-01-13 20:38:47 +00:00
|
|
|
# Copyright (C) 2024 Manuel Bustillo
|
|
|
|
|
2025-01-13 21:37:02 +01:00
|
|
|
# Copyright (C) 2024-2025 LibreWeddingPlanner contributors
|
2024-10-27 21:42:45 +00:00
|
|
|
|
2024-12-28 18:37:47 +01:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2024-07-31 20:58:47 +02:00
|
|
|
class AffinityGroupsHierarchy < Array
|
2025-01-19 20:58:33 +01:00
|
|
|
DEFAULT_DISCOMFORT = 1
|
2024-07-31 20:58:47 +02:00
|
|
|
|
|
|
|
def initialize
|
|
|
|
super
|
|
|
|
@references = {}
|
2024-11-01 11:55:32 +01:00
|
|
|
|
|
|
|
Group.roots.each do |group|
|
|
|
|
self << group.id
|
|
|
|
|
|
|
|
hydrate(group)
|
|
|
|
end
|
2025-01-19 20:58:33 +01:00
|
|
|
|
|
|
|
load_discomforts
|
|
|
|
freeze
|
2024-07-31 20:58:47 +02:00
|
|
|
end
|
|
|
|
|
2024-11-01 12:04:15 +01:00
|
|
|
def find(id)
|
|
|
|
@references[id]
|
2024-07-31 20:58:47 +02:00
|
|
|
end
|
|
|
|
|
2024-11-01 12:04:15 +01:00
|
|
|
def <<(id)
|
|
|
|
new_node = Tree::TreeNode.new(id)
|
|
|
|
super(new_node).tap { @references[id] = new_node }
|
2024-07-31 20:58:47 +02:00
|
|
|
end
|
|
|
|
|
2024-11-01 12:04:15 +01:00
|
|
|
def register_child(parent_id, child_id)
|
|
|
|
@references[parent_id] << Tree::TreeNode.new(child_id).tap { |child_node| @references[child_id] = child_node }
|
2024-07-31 20:58:47 +02:00
|
|
|
end
|
|
|
|
|
2024-11-01 12:04:15 +01:00
|
|
|
def distance(id_a, id_b)
|
|
|
|
return nil if @references[id_a].nil? || @references[id_b].nil?
|
2024-07-31 20:58:47 +02:00
|
|
|
|
2024-11-01 12:04:15 +01:00
|
|
|
@references[id_a].distance_to_common_ancestor(@references[id_b])
|
2024-07-31 20:58:47 +02:00
|
|
|
end
|
2024-11-01 11:55:32 +01:00
|
|
|
|
2025-01-19 20:58:33 +01:00
|
|
|
def discomfort(id_a, id_b)
|
|
|
|
return 0 if id_a == id_b
|
|
|
|
|
|
|
|
@discomforts[uuid_to_int(id_a) + uuid_to_int(id_b)] || DEFAULT_DISCOMFORT
|
|
|
|
end
|
|
|
|
|
|
|
|
def default_discomfort(id_a, id_b)
|
|
|
|
return 0 if id_a == id_b
|
|
|
|
|
|
|
|
dist = distance(id_a, id_b)
|
|
|
|
|
|
|
|
return DEFAULT_DISCOMFORT if dist.nil?
|
|
|
|
|
|
|
|
Rational(dist, dist + 1)
|
|
|
|
end
|
|
|
|
|
2024-11-01 11:55:32 +01:00
|
|
|
private
|
|
|
|
|
2025-01-19 20:58:33 +01:00
|
|
|
def load_discomforts
|
|
|
|
@load_discomforts ||= GroupAffinity.pluck(:group_a_id, :group_b_id,
|
|
|
|
:discomfort).each_with_object({}) do |(id_a, id_b, discomfort), acc|
|
|
|
|
acc[uuid_to_int(id_a) + uuid_to_int(id_b)] = discomfort
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def uuid_to_int(uuid)
|
|
|
|
uuid.gsub('-', '').hex
|
|
|
|
end
|
|
|
|
|
2024-11-01 11:55:32 +01:00
|
|
|
def hydrate(group)
|
|
|
|
group.children.each do |child|
|
|
|
|
register_child(group.id, child.id)
|
|
|
|
|
|
|
|
hydrate(child)
|
|
|
|
end
|
|
|
|
end
|
2024-07-31 20:58:47 +02:00
|
|
|
end
|