# Copyright (C) 2024-2025 LibreWeddingPlanner contributors # frozen_string_literal: true class TableSimulatorJob < ApplicationJob queue_as :default MIN_PER_TABLE = 8 MAX_PER_TABLE = 10 def perform(wedding_id, tables_arrangement_id) Rails.logger.info "Starting table simulation #{tables_arrangement_id} for wedding #{wedding_id}" ActsAsTenant.with_tenant(Wedding.find(wedding_id)) do engine = VNS::Engine.new engine.add_optimization(Tables::Swap) engine.add_optimization(Tables::Shift) tables_arrangement = TablesArrangement.find(tables_arrangement_id) initial_solution = Tables::Distribution.new( min_per_table: MIN_PER_TABLE, max_per_table: MAX_PER_TABLE, tables_arrangement_id: ) initial_solution.random_distribution(Guest.potential.shuffle) initial_solution.save! engine.notify_progress do |current_progress| tables_arrangement.update_columns(status: :in_progress, progress: current_progress) end engine.on_better_solution do |better_solution| better_solution.save! tables_arrangement.update_columns(discomfort: better_solution.discomfort) # TODO: remove? end engine.initial_solution = initial_solution engine.target_function(&:discomfort) best_solution = engine.run best_solution.save! tables_arrangement.update_columns(status: :completed) end end end