module Qwaiter
  module Distribution
    module DistributionMethods
      def epsilon
        @@epsilon ||= (10 ** -(Float::DIG - 1)).to_f
      end

      ##
      # Distribute a section of width w and height h in a length and a width scale
      # that makes n tables fit.
      #   distribute_lattice 10, 10, 3 #=> [5.0, 5.0]
      #   distribute_lattice 10, 10, 4 #=> [5.0, 5.0]
      ##
      def distribute_lattice(w, h, n)
        w, h = w.to_f, h.to_f
        area = w*h
        l = Math.sqrt(area.to_f/n)
        nx = w/l
        ny = h/l
        while (w/l + epsilon).floor * (h/l + epsilon).floor < n
          tx = w/l
          ty = h/l
          # The biggest remainder is closest to a fitting option
          # Just add one if no remainder wins and it still is not enough
          if tx.remainder(1) < epsilon && ty.remainder(1) < epsilon
            # Both divide, but there is no solution yet. Just add one
            l = [w/(tx + 1).round, h/(ty + 1).round].max
            nx = tx.ceil
            ny = ny.ceil
          elsif tx.remainder(1) > ty.remainder(1)
            nx = tx.ceil
            ny = (n.to_f/nx).ceil
            l = w/nx
          else
            ny = ty.ceil
            nx = (n.to_f/ny).ceil
            l = h/ny
          end

        end
        [w/nx, h/ny]
      end
    end
    include DistributionMethods
    extend DistributionMethods
  end
end
