Class: RoomPlan
Overview
== Schema Information
Table name: room_plans
Database name: primary
id :integer not null, primary key
heated_area :jsonb
heated_area_offset :decimal(, )
heated_sq_ft :decimal(, )
parent_room :integer
points :jsonb
room_area :decimal(, )
room_plan_fixtures_count :integer default(0), not null
step :integer
units :string
created_at :datetime not null
updated_at :datetime not null
party_id :integer
Indexes
index_room_plans_on_party_id (party_id) USING hash
Foreign Keys
fk_rails_... (party_id => parties.id) ON DELETE => cascade
Constant Summary
collapse
- DEFAULT_POINTS =
[
{ x: 243.84296513045595, y: 243.84296513045595 },
{ x: 731.5288953913679, y: 243.84296513045595 },
{ x: 731.5288953913679, y: 731.5288953913679 },
{ x: 243.84296513045595, y: 731.5288953913679 }
]
- SCREEN_UNITS_IN_A_METER =
200
- FEET_IN_A_METER =
3.2808
SCREEN_UNITS_IN_A_METER / FEET_IN_A_METER
- SCREEN_UNITS_IN_AN_INCH =
SCREEN_UNITS_IN_A_FOOT / 12
- DEFAULT_HEATED_AREA_WALL_OFFSET =
4.0
Class Method Summary
collapse
Instance Method Summary
collapse
ransackable_associations, ransackable_attributes, ransortable_attributes, #to_relation
#publish_event
Class Method Details
.get_nominal_wall_length(d) ⇒ Object
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
# File 'app/models/room_plan.rb', line 224
def self.get_nominal_wall_length(d)
d_in_ft = (d / SCREEN_UNITS_IN_A_FOOT).round(12)
ft = d_in_ft.floor
inches = ((d_in_ft - ft) * 12).round(2)
if inches % 1 == 0
inches = inches.to_i
end
if inches == 0
inches = ''
end
"#{ft}' #{inches}#{inches != '' ? '"' : ''}"
end
|
.has_fixtures ⇒ ActiveRecord::Relation<RoomPlan>
A relation of RoomPlans that are has fixtures. Active Record Scope
52
|
# File 'app/models/room_plan.rb', line 52
scope :has_fixtures, ->(val = 1) { where(RoomPlan[:room_plan_fixtures_count].gteq(val)) }
|
.migrate_legacy_fixtures ⇒ Object
This is a destructive operation, beware
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
# File 'app/models/room_plan.rb', line 77
def self.migrate_legacy_fixtures
RoomPlanFixture.delete_all
dt_key_map = DesignToolFixture.all.each_with_object({}) {|dtf, hsh| hsh[dtf['class_key']] = dtf.id}
puts "Design Tool Fixture map initializex with #{dt_key_map.size} entries"
RoomPlanFixture.transaction do
RoomPlan.find_each do |rp|
puts "Processing room plan #{rp.id}"
(rp.legacy_fixtures || {}).each do |f|
if class_key = f['key']
puts " - Converting fixture #{class_key}"
dtf_id = dt_key_map[class_key]
rp.room_plan_fixtures.create!(
design_tool_fixture_id: dtf_id,
fixture_data: f
)
else
puts " !! fixture class_key: #{class_key} is missing"
end
end
end
end
end
|
.options_for_select(ev = nil) ⇒ Object
63
64
65
66
|
# File 'app/models/room_plan.rb', line 63
def self.options_for_select(ev=nil)
res = all
res.map {|rp| [rp.selection_name, rp.id]}
end
|
.ransackable_scopes(auth_object = nil) ⇒ Object
72
73
74
|
# File 'app/models/room_plan.rb', line 72
def self.ransackable_scopes(auth_object = nil)
[:has_fixtures]
end
|
Instance Method Details
#build_heated_area ⇒ Object
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
# File 'app/models/room_plan.rb', line 146
def build_heated_area
heated_area&.reduce('') do |pathAcc, area| i = 0
pathAcc << area.reduce('') do |haAcc, shape| if shape.length === 1 and shape[0].kind_of? Array
shape = shape[0]
if shape.length === 1 and shape[0].kind_of? Array
shape = shape[0]
end
end
points = i.positive? ? shape.reverse : shape i += 1
points.reduce("#{haAcc} M #{points[0][0]},#{points[0][1]}") do |acc, (x, y)|
"#{acc} L #{x.to_f},#{y.to_f}"
end + 'z ' end
end
end
|
#build_walls ⇒ Object
166
167
168
169
170
171
|
# File 'app/models/room_plan.rb', line 166
def build_walls
walls = points.map { |wall| [wall['x'], wall['y']] }
walls.reduce("M #{walls[0][0]}, #{walls[0][1]} ") do |acc, (x, y)|
"#{acc} L #{x} #{y}"
end + ' z'
end
|
#clone(party_for_clone = nil) ⇒ Object
273
274
275
276
277
278
|
# File 'app/models/room_plan.rb', line 273
def clone(party_for_clone=nil)
my_clone = self.deep_dup
my_clone.party = party_for_clone if party_for_clone.present?
my_clone.save
my_clone
end
|
#deep_dup ⇒ Object
57
58
59
60
61
|
# File 'app/models/room_plan.rb', line 57
def deep_dup
deep_clone(include: :room_plan_fixtures) do |original, copy|
copy.parent_room = original.id if copy.is_a?(RoomPlan)
end
end
|
#determine_system_type_for_room_plan ⇒ Object
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
# File 'app/models/room_plan.rb', line 239
def determine_system_type_for_room_plan
rcs = room_configurations.includes(:room_type)
if rcs.empty?
'floor-heating'
else
environments = rcs.map { |rc| rc.room_type&.environment }.compact.uniq
if environments.include?('Outdoor')
'snow-melting'
else
'floor-heating'
end
end
end
|
#editing_locked? ⇒ Boolean
265
266
267
|
# File 'app/models/room_plan.rb', line 265
def editing_locked?
room_configurations.any? { |rc| rc.room_plan_editing_locked? }
end
|
#fixtures ⇒ Object
206
207
208
|
# File 'app/models/room_plan.rb', line 206
def fixtures
room_plan_fixtures.map(&:fixture_data)
end
|
#get_distance_between_points(a, b) ⇒ Object
198
199
200
|
# File 'app/models/room_plan.rb', line 198
def get_distance_between_points(a, b)
Math.sqrt((a['x'] - b['x']) ** 2 + (a['y'] - b['y']) ** 2);
end
|
#get_next_point(index) ⇒ Object
202
203
204
|
# File 'app/models/room_plan.rb', line 202
def get_next_point(index)
points[modulo(index + 1, points.length)]
end
|
#get_viewbox ⇒ Object
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
# File 'app/models/room_plan.rb', line 181
def get_viewbox
all_x, all_y = points.reduce([[], []]) { |(acc_x, acc_y), h| [[*acc_x, h['x']], [*acc_y, h['y']]] }
x_min = all_x.min
y_min = all_y.min
x_size = all_x.max - x_min
y_size = all_y.max - y_min
padding = 100
padding_x = padding padding_y = padding [
x_min - padding_x,
y_min - padding_y,
x_size + padding_x * 2,
y_size + padding_y * 2
].join(' ')
end
|
#hydrated_fixtures(include_visual: true) ⇒ Object
210
211
212
213
214
215
216
217
218
219
220
221
222
|
# File 'app/models/room_plan.rb', line 210
def hydrated_fixtures(include_visual: true)
preloaded_room_plan_fixtures.map do |rpf|
hsh = {
**rpf.fixture_data.symbolize_keys,
width: rpf.design_tool_fixture['size_x'] * SCREEN_UNITS_IN_AN_INCH,
height: rpf.design_tool_fixture['size_y'] * SCREEN_UNITS_IN_AN_INCH
}
if include_visual
hsh[:visual] = rpf.design_tool_fixture['visual']
end
hsh
end
end
|
#is_designable? ⇒ Boolean
177
178
179
|
# File 'app/models/room_plan.rb', line 177
def is_designable?
is_valid? && room_area.present? && fixtures.any? { |f| f['key'] == 'thermostat' }
end
|
#is_valid? ⇒ Boolean
173
174
175
|
# File 'app/models/room_plan.rb', line 173
def is_valid?
points.present? && fixtures.present?
end
|
#modulo(n, m) ⇒ Object
269
270
271
|
# File 'app/models/room_plan.rb', line 269
def modulo(n, m)
((n % m) + m) % m;
end
|
#ok_to_delete? ⇒ Boolean
261
262
263
|
# File 'app/models/room_plan.rb', line 261
def ok_to_delete?
room_configurations.empty?
end
|
#owned_or_cloned(customer) ⇒ Object
280
281
282
283
284
285
286
|
# File 'app/models/room_plan.rb', line 280
def owned_or_cloned(customer)
if party_id == customer.id
self
else
clone(customer)
end
end
|
46
|
# File 'app/models/room_plan.rb', line 46
belongs_to :party, inverse_of: :room_plans, optional: true
|
#preloaded_room_plan_fixtures ⇒ ActiveRecord::Relation<RoomPlanFixture>
50
|
# File 'app/models/room_plan.rb', line 50
has_many :preloaded_room_plan_fixtures, -> { eager_load(:design_tool_fixture) }, class_name: 'RoomPlanFixture'
|
#room_configurations ⇒ ActiveRecord::Relation<RoomConfiguration>
48
|
# File 'app/models/room_plan.rb', line 48
has_many :room_configurations, inverse_of: :room_plan, :dependent => :nullify
|
#room_plan_fixtures ⇒ ActiveRecord::Relation<RoomPlanFixture>
49
|
# File 'app/models/room_plan.rb', line 49
has_many :room_plan_fixtures, dependent: :destroy, autosave: true
|
#save_state(state) ⇒ Object
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'app/models/room_plan.rb', line 126
def save_state(state)
self.step = state['step']
self.units = state['units']
self.points = state['points']
self.room_area = state['roomArea']
self.heated_area = state['heatedArea']
self.heated_sq_ft = state['rawHeatedAreaSqft']
self.heated_area_offset = [2, state['heatedAreaOffset'].to_f]&.max
self.room_plan_fixtures.destroy_all
(state['fixtures'] || []).each do |fixture_data|
if design_tool_fixture = DesignToolFixture.find_by(class_key: fixture_data['key'])
self.room_plan_fixtures.build(design_tool_fixture_id: design_tool_fixture.id, fixture_data: fixture_data)
end
end
save
end
|
#selection_name ⇒ Object
68
69
70
|
# File 'app/models/room_plan.rb', line 68
def selection_name
"##{id}#{' by ' + party&.to_s if party}"
end
|
#serialize_data ⇒ Object
100
101
102
103
104
105
106
107
108
109
110
|
# File 'app/models/room_plan.rb', line 100
def serialize_data
{
fixtures: hydrated_fixtures(include_visual: false),
points: points.map { |p| [p['x'], p['y']] },
units: units || 'ftin',
roomArea: room_area&.to_f,
heatedArea: heated_area,
rawHeatedAreaSqft: heated_sq_ft&.to_f,
heatedAreaOffset: heated_area_offset&.to_f || DEFAULT_HEATED_AREA_WALL_OFFSET
}
end
|
#serialize_state ⇒ Object
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# File 'app/models/room_plan.rb', line 112
def serialize_state
{
step: step || 1,
id: self.id,
units: units || 'ftin',
points: points || DEFAULT_POINTS,
fixtures: fixtures,
roomArea: room_area&.to_f,
heatedArea: heated_area,
rawHeatedAreaSqft: heated_sq_ft&.to_f,
heatedAreaOffset: heated_area_offset&.to_f || DEFAULT_HEATED_AREA_WALL_OFFSET
}
end
|