Files
mozo-backend/app/models/section.rb
T

154 lines
4.1 KiB
Ruby

class Section
include SimplyStored::Couch
property :title
property :path, type: Array, default: []
belongs_to :supplier
has_many :tables
has_many :lists
has_many :orders
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 width
self.path.last.try(:first).to_f - self.path.first.try(:first).to_f
end
def height
self.path.last.try(:last).to_f - self.path.first.try(:last).to_f
end
def width=(val)
val = val.to_f
self.path[0] ||= [0.0, 0.0]
self.path[1] ||= [0.0, 0.0]
unless path[1][0] == val
self.path[1][0] = val
path_will_change!
end
end
def height=(val)
val = val.to_f
self.path[0] ||= [0.0, 0.0]
self.path[1] ||= [0.0, 0.0]
unless path[1][1] == val
self.path[1][1] = val
path_will_change!
end
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
ht[:occupied] = occupied_tables.include?(table)
ht[:needs_help] = ht[:occupied] ? active_lists.find{|l| l.table_id == table.id}.try(:needs_help).present? : false
ht[:needs_payment] = ht[:occupied] ? active_lists.find{|l| l.table_id == table.id}.try(:needs_payment).present? : false
h[:tables] << ht
end
@for_tables_as_json = h
end
def arrange_tables_in_grid
w = width
h = height
n = tables.size
l = Math.sqrt((w*h).to_f/n)
epsilon = (10 ** -(Float::DIG - 1)).to_f
while (w/l).floor * (h/l).floor < n # find a fitting combination
l = if w.remainder(l) < epsilon then (h/l).ceil
elsif h.remainder(l) < epsilon then (w/l).ceil
elsif w.remainder(l) < epsilon && h.remainder(l) < epsilon then [w / (w/l).ceil.succ, h / (h/l).ceil.succ].max # Failsafe for when both are valid and it still does not fit
else [w / (w/l).ceil, h / (h/l).ceil].max end
end
x0 = w.remainder(l - epsilon)/2 # Start with half a remainder space, will end with the other halve
x = x0
y = h.remainder(l - epsilon)/2
saves = []
for table in tables.sort_by(&:number)
if x + l > w + (1e4*epsilon) # New row, error = epsilon times possible tables
x = x0
y += l
end
table.position_x = x + (l/2) - (table_width/2) # Starting point of square + half the square (center) minus half the table size
table.position_y = y + (l/2) - (table_height/2)
saves << table.save
x += l
end
[l, saves.all?]
end
def arrange_tables_in_rows_of(n)
return unless n.present?
n = n.to_i
return unless n > 0
dx = width / n
dy = height / (tables.size.to_f/n).ceil
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)
x += dx
if (i + 1).multiple_of?( n )
x = 0.0
y += dy
end
table.save
end
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
# Method returning the sections table width
def table_width
2.0
end
# Method returning the sections table height
def table_height
2.0
end
end