Some checks failed
		
		
	
	Run unit tests / check-licenses (pull_request) Failing after 1m44s
				
			Run unit tests / rubocop (pull_request) Failing after 1m46s
				
			Run unit tests / copyright_notice (pull_request) Successful in 2m8s
				
			Run unit tests / unit_tests (pull_request) Failing after 3m30s
				
			Run unit tests / build-static-assets (pull_request) Has been skipped
				
			
		
			
				
	
	
		
			88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# Copyright (C) 2024-2025 LibreWeddingPlanner contributors
 | 
						|
 | 
						|
# frozen_string_literal: true
 | 
						|
 | 
						|
require_relative '../../extensions/tree_node_extension'
 | 
						|
 | 
						|
module Tables
 | 
						|
  class Distribution
 | 
						|
    class << self
 | 
						|
      def digest(wedding)
 | 
						|
        Digest::UUID.uuid_v5(wedding.id, wedding.guests.potential.order(:id).pluck(:id).join)
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    attr_accessor :tables, :min_per_table, :max_per_table, :hierarchy, :tables_arrangement_id
 | 
						|
 | 
						|
    def initialize(min_per_table:, max_per_table:, tables_arrangement_id:, hierarchy: AffinityGroupsHierarchy.new)
 | 
						|
      @min_per_table = min_per_table
 | 
						|
      @max_per_table = max_per_table
 | 
						|
      @hierarchy = hierarchy
 | 
						|
      @tables = []
 | 
						|
      @tables_arrangement_id = tables_arrangement_id
 | 
						|
    end
 | 
						|
 | 
						|
    def random_distribution(people, random: Random.new)
 | 
						|
      min_tables = (people.count * 1.0 / @max_per_table).ceil
 | 
						|
      max_tables = (people.count * 1.0 / @min_per_table).ceil
 | 
						|
      table_size = random.rand(min_tables..max_tables)
 | 
						|
      @tables = people.in_groups(table_size, false)
 | 
						|
                      .map { |group| Table.new(group) }
 | 
						|
                      .each { |table| table.min_per_table = @min_per_table }
 | 
						|
                      .each { |table| table.max_per_table = @max_per_table }
 | 
						|
    end
 | 
						|
 | 
						|
    def discomfort
 | 
						|
      @tables.map do |table|
 | 
						|
        local_discomfort(table)
 | 
						|
      end.sum
 | 
						|
    end
 | 
						|
 | 
						|
    def inspect
 | 
						|
      "#{@tables.count} tables, discomfort: #{discomfort}"
 | 
						|
    end
 | 
						|
 | 
						|
    def deep_dup
 | 
						|
      self.class.new(
 | 
						|
        min_per_table: @min_per_table,
 | 
						|
        max_per_table: @max_per_table,
 | 
						|
        hierarchy: @hierarchy,
 | 
						|
        tables_arrangement_id: @tables_arrangement_id
 | 
						|
      ).tap do |new_distribution|
 | 
						|
        new_distribution.tables = @tables.map(&:dup)
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    def save!
 | 
						|
      ActiveRecord::Base.transaction do
 | 
						|
        arrangement = TablesArrangement.find(tables_arrangement_id)
 | 
						|
 | 
						|
        self.tables_arrangement_id = arrangement.id
 | 
						|
 | 
						|
        arrangement.seats.delete_all
 | 
						|
 | 
						|
        records_to_store = []
 | 
						|
 | 
						|
        tables.each_with_index do |table, table_number|
 | 
						|
          table.each do |person|
 | 
						|
            records_to_store << { guest_id: person.id, tables_arrangement_id: arrangement.id, table_number: }
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        Seat.insert_all!(records_to_store)
 | 
						|
 | 
						|
        arrangement.update!(
 | 
						|
          discomfort:,
 | 
						|
          digest: self.class.digest(tables.first.first.wedding)
 | 
						|
        )
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    private
 | 
						|
 | 
						|
    def local_discomfort(table)
 | 
						|
      table.discomfort ||= DiscomfortCalculator.new(table:, hierarchy:).calculate
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |