File size: 10,232 Bytes
845939b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
"""
Building information input form for HVAC Load Calculator.
This module provides the UI components for entering building information.

Author: Dr Majed Abuseif
Date: March 2025
Version: 1.0.0
"""

import streamlit as st
import pandas as pd
import numpy as np
import pycountry
from typing import Dict, List, Any, Optional, Tuple
import os

# Import data models
from data.building_components import Orientation, ComponentType


class BuildingInfoForm:
    """Class for building information input form."""
    
    def __init__(self):
        """Initialize the building information form."""
        self.countries = sorted([country.name for country in pycountry.countries])
    
    def display(self):
        """Display the building information form."""
        self.display_building_info_form(st.session_state)
    
    def display_building_info_form(self, session_state: Dict[str, Any]) -> None:
        """Display building information input form in Streamlit."""
        st.header("Building Information")
        
        if "building_info" not in session_state:
            session_state["building_info"] = {
                "project_name": "",
                "building_name": "",
                "country": "",
                "city": "",
                "building_type": "",
                "floor_area": 0.0,
                "width": 0.0,
                "depth": 0.0,
                "building_height": 3.0,
                "orientation": "NORTH",
                "operating_hours": "8:00-18:00"
            }
        
        default_values = {
            "project_name": "",
            "building_name": "",
            "country": "",
            "city": "",
            "building_type": "",
            "floor_area": 0.0,
            "width": 0.0,
            "depth": 0.0,
            "building_height": 3.0,
            "orientation": "NORTH",
            "operating_hours": "8:00-18:00"
        }
        
        for key, default_value in default_values.items():
            if key not in session_state["building_info"]:
                session_state["building_info"][key] = default_value
        
        if "data_saved" not in session_state:
            session_state["data_saved"] = False
        
        with st.form(key="building_info_form"):
            st.subheader("Project Information")
            
            col1, col2 = st.columns(2)
            with col1:
                session_state["building_info"]["project_name"] = st.text_input(
                    "Project Name",
                    value=session_state["building_info"]["project_name"],
                    help="Enter the project's identification name"
                )
                session_state["building_info"]["building_name"] = st.text_input(
                    "Building Name",
                    value=session_state["building_info"]["building_name"],
                    help="Enter the building's identification name"
                )
            
            with col2:
                session_state["building_info"]["country"] = st.selectbox(
                    "Country",
                    options=[""] + self.countries,
                    index=0 if not session_state["building_info"]["country"] else 
                          self.countries.index(session_state["building_info"]["country"]) + 1,
                    help="Select the building's country location"
                )
                session_state["building_info"]["city"] = st.text_input(
                    "City",
                    value=session_state["building_info"]["city"],
                    help="Enter the building's city location"
                )
            
            st.subheader("Building Characteristics")
            
            col1, col2 = st.columns(2)
            with col1:
                session_state["building_info"]["building_type"] = st.selectbox(
                    "Building Type",
                    ["Residential", "Office", "Retail", "Educational", "Healthcare", "Industrial", "Other"],
                    index=1 if session_state["building_info"]["building_type"] == "" else 
                          ["Residential", "Office", "Retail", "Educational", "Healthcare", "Industrial", "Other"].index(session_state["building_info"]["building_type"]),
                    help="Select the building's purpose or usage type"
                )
            
            with col2:
                session_state["building_info"]["building_height"] = st.number_input(
                    "Building Height (m)",
                    min_value=2.0,
                    max_value=1000.0,
                    value=float(session_state["building_info"]["building_height"]),
                    step=0.1,
                    help="Enter the total height of the building in meters"
                )
            
            st.subheader("Building Dimensions")
            session_state["building_info"]["floor_area"] = st.number_input(
                "Total Floor Area (m²)",
                min_value=0.0,
                value=float(session_state["building_info"]["floor_area"]),
                step=10.0,
                help="Enter the total floor area of the building in square meters (optional if width and depth provided)"
            )
            
            # Center the OR using columns
            col1, col2, col3 = st.columns([2, 1, 2])
            with col2:
                st.markdown("Enter the total floor area above OR the building width and depth below")
            
            col1, col2 = st.columns(2)
            with col1:
                session_state["building_info"]["width"] = st.number_input(
                    "Width (m)",
                    min_value=0.0,
                    value=float(session_state["building_info"]["width"]),
                    step=1.0,
                    help="Enter the building's width in meters (optional if area provided)"
                )
            with col2:
                session_state["building_info"]["depth"] = st.number_input(
                    "Depth (m)",
                    min_value=0.0,
                    value=float(session_state["building_info"]["depth"]),
                    step=1.0,
                    help="Enter the building's depth in meters (optional if area provided)"
                )
            
            st.subheader("Building Orientation")
            session_state["building_info"]["orientation"] = st.selectbox(
                "Building Orientation",
                ["NORTH", "NORTHEAST", "EAST", "SOUTHEAST", "SOUTH", "SOUTHWEST", "WEST", "NORTHWEST"],
                index=["NORTH", "NORTHEAST", "EAST", "SOUTHEAST", "SOUTH", "SOUTHWEST", "WEST", "NORTHWEST"].index(session_state["building_info"]["orientation"]),
                help="Select the direction of the building's main facade"
            )
            
            st.subheader("Operating Hours")
            session_state["building_info"]["operating_hours"] = st.text_input(
                "Operating Hours",
                value=session_state["building_info"]["operating_hours"],
                help="Enter the building's daily operating hours (e.g., 8:00-18:00)"
            )
            
            submitted = st.form_submit_button("Save Building Information")
            
            if submitted:
                valid, errors = self.validate_building_info(session_state["building_info"])
                if not valid:
                    for error in errors:
                        st.error(error)
                else:
                    if session_state["building_info"]["width"] > 0 and session_state["building_info"]["depth"] > 0:
                        calculated_area = session_state["building_info"]["width"] * session_state["building_info"]["depth"]
                        if session_state["building_info"]["floor_area"] == 0:
                            session_state["building_info"]["floor_area"] = calculated_area
                    
                    total_volume = session_state["building_info"]["floor_area"] * session_state["building_info"]["building_height"]
                    
                    session_state["save_results"] = {
                        "success": "Building information saved successfully!",
                        "area": f"Total Floor Area: {session_state['building_info']['floor_area']:.1f} m²",
                        "volume": f"Total Building Volume: {total_volume:.1f} m³"
                    }
                    session_state["data_saved"] = True
        
        # Display results if they exist
        if "save_results" in session_state and session_state["data_saved"]:
            st.success(session_state["save_results"]["success"])
            st.info(session_state["save_results"]["area"])
            st.info(session_state["save_results"]["volume"])
        
        # Proceed button with immediate navigation
        if session_state["data_saved"]:
            if st.button("Proceed to Climate Data"):
                session_state["page"] = "Climate Data"
                session_state["data_saved"] = False
                if "save_results" in session_state:
                    del session_state["save_results"]
    
    @staticmethod
    def validate_building_info(building_info: Dict[str, Any]) -> Tuple[bool, List[str]]:
        """Validate building information."""
        valid = True
        errors = []
        
        required_fields = ["project_name", "building_name", "country", "city", "building_type"]
        for field in required_fields:
            if field not in building_info or not building_info[field]:
                valid = False
                errors.append(f"Missing required field: {field}")
        
        if building_info.get("floor_area", 0) <= 0 and (building_info.get("width", 0) <= 0 or building_info.get("depth", 0) <= 0):
            valid = False
            errors.append("Must provide either floor area or both width and depth dimensions")
        
        if building_info.get("building_height", 0) <= 0:
            valid = False
            errors.append("Building height must be greater than zero")
        
        return valid, errors


if __name__ == "__main__":
    form = BuildingInfoForm()
    form.display()