class Section include SimplyStored::Couch include Qwaiter::Distribution include ActiveModel::SerializerSupport property :title property :path, type: Array, default: [[0.0, 0.0], [20.0, 0.0], [20.0, 30.0], [0.0, 30.0]] # default width 20m height 30m belongs_to :supplier has_many :tables has_many :lists has_many :orders has_many :section_elements attr_protected :supplier_id validates :title, presence: true validates :supplier_id, presence: true view :by_supplier_id_and_id, key: [:supplier_id, :_id] def occupied_tables return @occupied_tables if @occupied_tables.present? @active_lists = List.active_for_section(self.id) @active_lists.include_relation(:table) @occupied_tables = @active_lists.map(&:table) end def active_lists return @active_lists if @active_lists.present? @active_lists = List.active_for_section(self.id) end def active_orders @active_orders ||= Order.active_for_supplier_and_section(supplier_id, id) end def width x_coords = path.map(&:first) x_coords.max - x_coords.min end def height y_coords = path.map(&:last) y_coords.max - y_coords.min end def width=(val) val = val.to_f return val if width == val self.path[0] ||= [0.0, 0.0] self.path[1] ||= [0.0, 0.0] self.path[2] ||= [0.0, 0.0] self.path[3] ||= [0.0, 0.0] path[0][0] = 0 path[1][0] = val path[2][0] = val path[3][0] = 0 path_will_change! val end def height=(val) val = val.to_f return val if height == val self.path[0] ||= [0.0, 0.0] self.path[1] ||= [0.0, 0.0] self.path[2] ||= [0.0, 0.0] self.path[3] ||= [0.0, 0.0] path[0][1] = 0 path[1][1] = 0 path[2][1] = val path[3][1] = val path_will_change! val end def tables_with_active_list_id Table.enrich_active_list_id(tables) end #def as_json(*) #super.merge(width: width, height: height) #end def for_tables_as_json return @for_tables_as_json if @for_tables_as_json.present? h = as_json h[:tables] = [] for table in tables ht = table.as_json table_list = active_lists.find{|l| l.table_id == table.id} ht[:occupied] = occupied_tables.include?(table) ht[:needs_help] = ht[:occupied] && table_list ? table_list.needs_help? : false ht[:needs_payment] = ht[:occupied] && table_list ? table_list.needs_payment? : false ht[:active_order] = ht[:occupied] && table_list ? active_orders.any?{|o| o.list_id == table_list.id } : false h[:tables] << ht end @for_tables_as_json = h end def arrange_tables_in_grid w = width h = height n = tables.size return false unless w > 0 && h > 0 && n > 0 lx, ly = distribute_lattice(w, h, n) x0 = lx/2 x = x0 y = ly/2 saves = [] for table in tables.sort_by(&:number) if x > w + (1e4*epsilon) # New row, error = epsilon times possible tables in a row x = x0 y += ly end table.position_x = x - (table.width/2) # Starting point of square + half the square (center) minus half the table size table.position_y = y - (table.height/2) saves << table.save x += lx end saves.all? end def arrange_tables_in_rows_of(n) return false unless n.present? n = n.to_i return false unless n > 0 dx = width / n dy = height / (tables.size.to_f/n).ceil x = 0.0 y = 0.0 saves = [] tables.sort_by(&:number).each.with_index do |table, i| table.position_x = x + (dx/2) - (table.width/2) table.position_y = y + (dy/2) - (table.height/2) x += dx if (i + 1).multiple_of?( n ) x = 0.0 y += dy end saves << table.save end return saves.all? end def arrange_tables_in_columns_of(n) return unless n.present? n = n.to_i return unless n > 0 dx = width / (tables.size.to_f/n).ceil dy = height / n x = 0.0 y = 0.0 tables.sort_by(&:number).each.with_index do |table, i| table.position_x = x + (dx/2) - (table.width/2) table.position_y = y + (dy/2) - (table.height/2) y += dy if (i + 1).multiple_of?( n ) y = 0.0 x += dx end table.save end end end