All checks were successful
		
		
	
	Check usage of free licenses / check-licenses (pull_request) Successful in 1m38s
				
			Add copyright notice / copyright_notice (pull_request) Successful in 3m16s
				
			Run unit tests / unit_tests (pull_request) Successful in 5m31s
				
			Build Nginx-based docker image / build-static-assets (pull_request) Successful in 41m31s
				
			
		
			
				
	
	
		
			78 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			78 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # Copyright (C) 2024-2025 LibreWeddingPlanner contributors
 | |
| 
 | |
| # frozen_string_literal: true
 | |
| 
 | |
| class AffinityGroupsHierarchy < Array
 | |
|   DEFAULT_DISCOMFORT = 1
 | |
| 
 | |
|   def initialize
 | |
|     super
 | |
|     @references = {}
 | |
| 
 | |
|     Group.roots.each do |group|
 | |
|       self << group.id
 | |
| 
 | |
|       hydrate(group)
 | |
|     end
 | |
| 
 | |
|     discomforts
 | |
|     freeze
 | |
|   end
 | |
| 
 | |
|   def find(id)
 | |
|     @references[id]
 | |
|   end
 | |
| 
 | |
|   def <<(id)
 | |
|     new_node = Tree::TreeNode.new(id)
 | |
|     super(new_node).tap { @references[id] = new_node }
 | |
|   end
 | |
| 
 | |
|   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(id_a, id_b)
 | |
|     return nil if @references[id_a].nil? || @references[id_b].nil?
 | |
| 
 | |
|     @references[id_a].distance_to_common_ancestor(@references[id_b])
 | |
|   end
 | |
| 
 | |
|   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
 | |
| 
 | |
|   private
 | |
| 
 | |
|   def discomforts
 | |
|     @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
 | |
| 
 | |
|   def hydrate(group)
 | |
|     group.children.each do |child|
 | |
|       register_child(group.id, child.id)
 | |
| 
 | |
|       hydrate(child)
 | |
|     end
 | |
|   end
 | |
| end
 |