mabuseif commited on
Commit
dac7f93
·
verified ·
1 Parent(s): 9b75a32

Update app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +33 -9
app/main.py CHANGED
@@ -2,6 +2,7 @@
2
  HVAC Calculator Code Documentation.
3
  Updated 2025-05-02: Integrated skylights, surface color, glazing type, frame type, and drapery adjustments from main_new.py.
4
  Updated 2025-05-02: Enhanced per Plan.txt to include winter design temperature, humidity, building height, ventilation rate, internal load enhancements, and calculation parameters.
 
5
  """
6
 
7
  import streamlit as st
@@ -52,6 +53,10 @@ VENTILATION_RATES = {
52
  "Custom": {"people_rate": 0.0, "area_rate": 0.0}
53
  }
54
 
 
 
 
 
55
  class HVACCalculator:
56
  def __init__(self):
57
  st.set_page_config(
@@ -225,6 +230,13 @@ class HVACCalculator:
225
  return False, f"Glazing type missing for {component_type}: {comp.name}"
226
  if getattr(comp, 'frame_type', None) is None:
227
  return False, f"Frame type missing for {component_type}: {comp.name}"
 
 
 
 
 
 
 
228
 
229
  # Validate ventilation rate
230
  if building_info.get('ventilation_rate', 0) < 0:
@@ -279,18 +291,30 @@ class HVACCalculator:
279
 
280
  return True, "Valid load."
281
 
282
- def parse_latitude(self, latitude: Any) -> float:
283
- """Parse latitude from string or float to float value."""
284
  try:
285
  if isinstance(latitude, (int, float)):
286
- return float(latitude)
287
- if isinstance(latitude, str):
288
  lat_str = latitude.strip().upper().replace('N', '').replace('S', '')
289
- return float(lat_str)
290
- raise ValueError("Invalid latitude format")
 
 
 
 
 
 
 
 
 
 
 
 
291
  except (ValueError, AttributeError) as e:
292
- st.error(f"Invalid latitude: {latitude}. Using default 32.0.")
293
- return 32.0 # Default to 32N
294
 
295
  def display_internal_loads(self):
296
  st.title("Internal Loads")
@@ -1131,7 +1155,7 @@ class HVACCalculator:
1131
  'lights': {
1132
  'power': sum(load['power'] for load in internal_loads.get('lighting', [])),
1133
  'use_factor': internal_loads.get('lighting', [{}])[0].get('usage_factor', 0.8),
1134
- 'hours_operation': internal_loads.get('lighting', [{}])[0].get('hours_in_operation', '8h'),
1135
  'zone_type': internal_loads.get('lighting', [{}])[0].get('zone_type', 'A')
1136
  },
1137
  'equipment': {
 
2
  HVAC Calculator Code Documentation.
3
  Updated 2025-05-02: Integrated skylights, surface color, glazing type, frame type, and drapery adjustments from main_new.py.
4
  Updated 2025-05-02: Enhanced per Plan.txt to include winter design temperature, humidity, building height, ventilation rate, internal load enhancements, and calculation parameters.
5
+ Updated 2025-05-09: Fixed latitude parsing to return string (e.g., "24N") to match ASHRAE table keys and added group validation.
6
  """
7
 
8
  import streamlit as st
 
53
  "Custom": {"people_rate": 0.0, "area_rate": 0.0}
54
  }
55
 
56
+ # Valid wall and roof groups for ASHRAE CLTD tables (adjust based on ashrae_tables.py)
57
+ VALID_WALL_GROUPS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
58
+ VALID_ROOF_GROUPS = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
59
+
60
  class HVACCalculator:
61
  def __init__(self):
62
  st.set_page_config(
 
230
  return False, f"Glazing type missing for {component_type}: {comp.name}"
231
  if getattr(comp, 'frame_type', None) is None:
232
  return False, f"Frame type missing for {component_type}: {comp.name}"
233
+ # NEW: Validate wall and roof groups
234
+ if component_type == 'walls':
235
+ if getattr(comp, 'wall_group', '') not in VALID_WALL_GROUPS:
236
+ return False, f"Invalid wall group '{comp.wall_group}' for {comp.name}. Valid groups: {', '.join(VALID_WALL_GROUPS)}"
237
+ if component_type == 'roofs':
238
+ if getattr(comp, 'roof_group', '') not in VALID_ROOF_GROUPS:
239
+ return False, f"Invalid roof group '{comp.roof_group}' for {comp.name}. Valid groups: {', '.join(VALID_ROOF_GROUPS)}"
240
 
241
  # Validate ventilation rate
242
  if building_info.get('ventilation_rate', 0) < 0:
 
291
 
292
  return True, "Valid load."
293
 
294
+ def parse_latitude(self, latitude: Any) -> str:
295
+ """Parse latitude from string or number to ASHRAE table format (e.g., '24N')."""
296
  try:
297
  if isinstance(latitude, (int, float)):
298
+ lat_value = float(latitude)
299
+ elif isinstance(latitude, str):
300
  lat_str = latitude.strip().upper().replace('N', '').replace('S', '')
301
+ lat_value = float(lat_str)
302
+ else:
303
+ raise ValueError("Invalid latitude format")
304
+
305
+ # Convert to ASHRAE table format (e.g., '24N', '32N')
306
+ if lat_value in [24, 32, 40, 48]: # Common ASHRAE latitudes
307
+ return f"{int(lat_value)}N"
308
+ else:
309
+ # Round to nearest supported latitude
310
+ supported_latitudes = [24, 32, 40, 48]
311
+ closest_lat = min(supported_latitudes, key=lambda x: abs(x - lat_value))
312
+ st.warning(f"Latitude {lat_value} not in ASHRAE tables. Using closest: {closest_lat}N")
313
+ return f"{closest_lat}N"
314
+
315
  except (ValueError, AttributeError) as e:
316
+ st.error(f"Invalid latitude: {latitude}. Using default 32N.")
317
+ return "32N" # Default to 32N
318
 
319
  def display_internal_loads(self):
320
  st.title("Internal Loads")
 
1155
  'lights': {
1156
  'power': sum(load['power'] for load in internal_loads.get('lighting', [])),
1157
  'use_factor': internal_loads.get('lighting', [{}])[0].get('usage_factor', 0.8),
1158
+ 'hours_operation': internal_loads.get('lighting', [{}])[0].get('hours_in_operation』, '8h'),
1159
  'zone_type': internal_loads.get('lighting', [{}])[0].get('zone_type', 'A')
1160
  },
1161
  'equipment': {