require_relative '../../extensions/tree_node_extension' module Tables class Distribution def initialize(min_per_table:, max_per_table:) @min_per_table = min_per_table @max_per_table = max_per_table @tables = {} end def tables @tables.values.freeze end def deep_freeze @tables.each_value(&:freeze) @tables.freeze freeze end def replace(table) @tables[table.id] = table end def dup super.tap do |new_distribution| new_distribution.instance_variable_set(:@tables, @tables.dup) end end def <<(array) Table.new(array).tap do |table| @tables[table.id] = table end end def random_distribution(people) @tables = {} self << people.slice!(0..rand(@min_per_table..@max_per_table)) while people.any? @tables.freeze freeze end def discomfort tables.map(&:discomfort).sum end def inspect "#{tables.count} tables, discomfort: #{discomfort}" end def pretty_print tables.map.with_index do |table, i| "Table #{i + 1} (#{table.count} ppl): (#{table.discomfort}) #{table.map(&:full_name).join(', ')}" end.join("\n") end def deep_dup self.class.new(min_per_table: @min_per_table, max_per_table: @max_per_table).tap do |new_distribution| tables.each do |table| new_distribution << table.dup end end end def save! ActiveRecord::Base.transaction do arrangement = TablesArrangement.create! 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:) end end end end