Spaces:
Sleeping
Sleeping
Update app/internal_loads.py
Browse files- app/internal_loads.py +3 -245
app/internal_loads.py
CHANGED
@@ -20,7 +20,8 @@ import uuid
|
|
20 |
import plotly.graph_objects as go
|
21 |
import plotly.express as px
|
22 |
from typing import Dict, List, Any, Optional, Tuple, Union
|
23 |
-
|
|
|
24 |
|
25 |
# Configure logging
|
26 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
@@ -29,171 +30,6 @@ logger = logging.getLogger(__name__)
|
|
29 |
# Define constants
|
30 |
LOAD_TYPES = ["People", "Lighting", "Equipment", "Ventilation & Infiltration", "Schedules"]
|
31 |
|
32 |
-
# People activity levels data as provided by user
|
33 |
-
PEOPLE_ACTIVITY_LEVELS = {
|
34 |
-
name: {
|
35 |
-
"metabolic_rate_met": data[0],
|
36 |
-
"metabolic_rate_w": data[1],
|
37 |
-
"sensible_min_w": data[2],
|
38 |
-
"sensible_max_w": data[3],
|
39 |
-
"latent_min_w": data[4],
|
40 |
-
"latent_max_w": data[5]
|
41 |
-
} for name, data in [
|
42 |
-
("Seated, at Rest (Quiet, Reading, Writing)", [1.0, 110, 20, 24, 9, 12]),
|
43 |
-
("Seated, Light Office Work (Typing, Filing)", [1.1, 125, 24, 27, 12, 15]),
|
44 |
-
("Standing, Light Work (Filing, Walking Slowly)", [1.35, 155, 30, 35, 18, 24]),
|
45 |
-
("Walking, Moderate Pace (2–3 mph / 3.2–4.8 km/h)", [2.0, 210, 41, 47, 30, 35]),
|
46 |
-
("Light Machine Work (Assembly, Small Tools)", [2.35, 250, 47, 56, 35, 44]),
|
47 |
-
("Moderate Work (Walking with Loads, Lifting)", [3.0, 310, 59, 68, 50, 59]),
|
48 |
-
("Heavy Work (Carrying Heavy Loads, Shoveling)", [4.0, 425, 73, 88, 73, 88]),
|
49 |
-
("Dancing (Moderate to Vigorous)", [3.5, 400, 59, 88, 59, 73]),
|
50 |
-
("Athletics/Exercise (Vigorous)", [6.0, 600, 88, 117, 88, 117])
|
51 |
-
]
|
52 |
-
}
|
53 |
-
|
54 |
-
# Default building internals data as provided by user
|
55 |
-
DEFAULT_BUILDING_INTERNALS = {
|
56 |
-
name: {
|
57 |
-
"lighting_density": data[0], # W/m²
|
58 |
-
"diversity_factor": data[1],
|
59 |
-
"equipment_heat_gains": {
|
60 |
-
"sensible": data[2],
|
61 |
-
"latent": data[3],
|
62 |
-
"convective": data[4],
|
63 |
-
"radiant": data[5]
|
64 |
-
},
|
65 |
-
"ventilation_rate": data[6], # L/s·person or L/s·m²
|
66 |
-
"air_change_rate": data[7], # ACH
|
67 |
-
"schedule_type": data[8]
|
68 |
-
} for name, data in [
|
69 |
-
("Residential - Single-Family Detached", [8.0, 0.7, 3.5, 1.5, 2.0, 1.5, 7.5, 0.35, "residential"]),
|
70 |
-
("Residential - Single-Family Attached", [8.0, 0.7, 3.5, 1.5, 2.0, 1.5, 7.5, 0.35, "residential"]),
|
71 |
-
("Residential - Multifamily (Low-rise and High-rise)", [8.0, 0.75, 4.0, 2.0, 2.5, 1.5, 8.0, 0.35, "residential"]),
|
72 |
-
("Residential - Dormitories", [10.0, 0.8, 5.0, 2.0, 3.0, 2.0, 10.0, 0.5, "residential"]),
|
73 |
-
("Residential - Hotels and Motels", [12.0, 0.85, 6.0, 2.5, 3.5, 2.5, 10.0, 0.5, "hotel"]),
|
74 |
-
("Commercial/Retail - Strip Mall", [15.0, 0.9, 12.0, 2.0, 6.0, 6.0, 10.0, 1.0, "retail"]),
|
75 |
-
("Commercial/Retail - Enclosed Mall", [18.0, 0.9, 15.0, 2.0, 8.0, 7.0, 10.0, 1.2, "retail"]),
|
76 |
-
("Commercial/Retail - Department Store", [16.0, 0.9, 14.0, 2.0, 7.0, 7.0, 10.0, 1.0, "retail"]),
|
77 |
-
("Commercial/Retail - Supermarket", [18.0, 0.95, 18.0, 3.0, 10.0, 8.0, 12.0, 1.2, "retail"]),
|
78 |
-
("Commercial/Retail - Convenience Store", [20.0, 0.95, 20.0, 4.0, 12.0, 8.0, 12.0, 1.5, "retail"]),
|
79 |
-
("Commercial/Retail - Fast Food Restaurant", [14.0, 0.85, 18.0, 6.0, 10.0, 8.0, 15.0, 1.5, "retail"]),
|
80 |
-
("Commercial/Retail - Full-Service Restaurant", [14.0, 0.85, 16.0, 5.0, 9.0, 7.0, 15.0, 1.5, "retail"]),
|
81 |
-
("Office - Small Office (<1,000 m²)", [12.0, 0.8, 10.0, 1.0, 5.0, 5.0, 10.0, 0.9, "office"]),
|
82 |
-
("Office - Medium Office (≈5,000 m²)", [12.0, 0.8, 10.0, 1.0, 5.0, 5.0, 10.0, 1.0, "office"]),
|
83 |
-
("Office - Large Office (>10,000 m²)", [12.0, 0.8, 10.0, 1.0, 5.0, 5.0, 10.0, 1.0, "office"]),
|
84 |
-
("Office - Call Centre", [13.0, 0.85, 12.0, 1.5, 6.0, 6.0, 12.0, 1.2, "office"]),
|
85 |
-
("Educational - Primary School", [14.0, 0.85, 6.0, 2.0, 3.0, 3.0, 10.0, 1.0, "school"]),
|
86 |
-
("Educational - Secondary School", [14.0, 0.85, 6.5, 2.0, 3.5, 3.0, 10.0, 1.0, "school"]),
|
87 |
-
("Educational - University/College Classroom", [14.0, 0.85, 7.0, 2.0, 4.0, 3.0, 10.0, 1.0, "school"]),
|
88 |
-
("Educational - Lecture Hall", [15.0, 0.85, 8.0, 2.0, 4.0, 4.0, 10.0, 1.0, "school"]),
|
89 |
-
("Educational - Laboratory", [16.0, 0.9, 20.0, 4.0, 12.0, 8.0, 15.0, 2.5, "school"]),
|
90 |
-
("Educational - Library", [13.0, 0.8, 5.0, 1.0, 2.5, 2.5, 8.0, 0.7, "school"]),
|
91 |
-
("Healthcare - Hospital (Inpatient)", [15.0, 0.95, 20.0, 5.0, 10.0, 10.0, 20.0, 2.0, "hospital"]),
|
92 |
-
("Healthcare - Outpatient Clinic/Medical Office", [14.0, 0.9, 15.0, 3.0, 8.0, 7.0, 15.0, 1.5, "hospital"]),
|
93 |
-
("Healthcare - Nursing Home/Aged Care", [13.0, 0.85, 10.0, 3.0, 5.0, 5.0, 12.0, 1.0, "hospital"]),
|
94 |
-
("Assembly - Auditorium", [12.0, 0.9, 8.0, 2.0, 4.0, 4.0, 10.0, 1.0, "assembly"]),
|
95 |
-
("Assembly - Theatre/Performing Arts", [12.0, 0.9, 10.0, 2.0, 5.0, 5.0, 10.0, 1.0, "assembly"]),
|
96 |
-
("Assembly - Convention Centre", [14.0, 0.9, 12.0, 3.0, 6.0, 6.0, 12.0, 1.2, "assembly"]),
|
97 |
-
("Assembly - Gymnasium/Sports Arena", [15.0, 0.9, 14.0, 4.0, 8.0, 6.0, 12.0, 1.5, "assembly"]),
|
98 |
-
("Assembly - Religious Building", [12.0, 0.85, 6.0, 1.5, 3.0, 3.0, 10.0, 1.0, "assembly"]),
|
99 |
-
("Industrial - Light Manufacturing", [13.0, 0.9, 20.0, 2.0, 10.0, 10.0, 15.0, 1.5, "industrial"]),
|
100 |
-
("Industrial - Heavy Manufacturing", [13.0, 0.95, 30.0, 3.0, 15.0, 15.0, 20.0, 2.0, "industrial"]),
|
101 |
-
("Industrial - Warehouse (Unconditioned or Semi-conditioned)", [10.0, 0.7, 8.0, 1.0, 4.0, 4.0, 6.0, 0.5, "industrial"]),
|
102 |
-
("Industrial - Data Centre/Server Room", [15.0, 1.0, 80.0, 0.0, 80.0, 0.0, 20.0, 2.0, "industrial"]),
|
103 |
-
("Public and Institutional - Courthouse", [14.0, 0.85, 8.0, 2.0, 4.0, 4.0, 10.0, 1.0, "office"]),
|
104 |
-
("Public and Institutional - Police Station", [13.0, 0.85, 8.0, 2.0, 4.0, 4.0, 10.0, 1.0, "office"]),
|
105 |
-
("Public and Institutional - Fire Station", [13.0, 0.85, 8.0, 2.0, 4.0, 4.0, 10.0, 1.0, "office"]),
|
106 |
-
("Public and Institutional - Post Office", [14.0, 0.85, 10.0, 2.0, 5.0, 5.0, 10.0, 1.0, "office"]),
|
107 |
-
("Public and Institutional - Museum", [15.0, 0.9, 12.0, 2.0, 6.0, 6.0, 12.0, 1.2, "office"]),
|
108 |
-
("Lodging - Hotel (Full-Service, Midscale, or Economy)", [12.0, 0.85, 6.0, 2.0, 3.0, 3.0, 10.0, 0.8, "hotel"]),
|
109 |
-
("Lodging - Motel", [12.0, 0.85, 5.0, 2.0, 3.0, 2.0, 8.0, 0.8, "hotel"]),
|
110 |
-
("Lodging - Resort", [12.0, 0.85, 7.0, 2.5, 3.5, 3.5, 10.0, 0.8, "hotel"]),
|
111 |
-
("Transportation - Airport Terminal", [14.0, 0.95, 10.0, 3.0, 6.0, 4.0, 15.0, 1.5, "transport"]),
|
112 |
-
("Transportation - Train/Bus Station", [14.0, 0.9, 9.0, 2.0, 5.0, 4.0, 12.0, 1.2, "transport"]),
|
113 |
-
("Transportation - Car Park (Enclosed)", [8.0, 0.7, 2.0, 0.0, 2.0, 0.0, 5.0, 0.5, "transport"]),
|
114 |
-
("Other", [12.0, 0.85, 10.0, 2.0, 5.0, 5.0, 10.0, 1.0, "default"]),
|
115 |
-
("Continuous", [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, "continuous"]),
|
116 |
-
("Custom", [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, "custom"])
|
117 |
-
]
|
118 |
-
}
|
119 |
-
|
120 |
-
|
121 |
-
# Default schedule templates
|
122 |
-
DEFAULT_SCHEDULE_TEMPLATES = {
|
123 |
-
"residential": {
|
124 |
-
"description": "Typical residential usage (peaks morning and evening)",
|
125 |
-
"weekday": [0.3, 0.3, 0.3, 0.3, 0.4, 0.5, 0.6, 0.7, 0.4, 0.3, 0.3, 0.4,
|
126 |
-
0.5, 0.5, 0.6, 0.8, 0.9, 1.0, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3],
|
127 |
-
"weekend": [0.4, 0.4, 0.4, 0.4, 0.5, 0.6, 0.7, 0.9, 0.8, 0.7, 0.7, 0.6,
|
128 |
-
0.7, 0.8, 0.9, 1.0, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.4]
|
129 |
-
},
|
130 |
-
"office": {
|
131 |
-
"description": "Standard office hours (8 AM - 6 PM)",
|
132 |
-
"weekday": [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.5, 1.0, 1.0, 1.0, 1.0,
|
133 |
-
0.8, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1],
|
134 |
-
"weekend": [0.1] * 24
|
135 |
-
},
|
136 |
-
"commercial": {
|
137 |
-
"description": "Retail hours (9 AM - 9 PM)",
|
138 |
-
"weekday": [0.1, 0.1, 0.1, 0.1, 0.1, 0.2, 0.4, 0.7, 1.0, 1.0, 1.0, 1.0,
|
139 |
-
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.7, 0.5, 0.3, 0.2, 0.1, 0.1],
|
140 |
-
"weekend": [0.1, 0.1, 0.1, 0.1, 0.2, 0.4, 0.7, 1.0, 1.0, 1.0, 1.0, 1.0,
|
141 |
-
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.8, 0.6, 0.4, 0.2, 0.1, 0.1]
|
142 |
-
},
|
143 |
-
"educational": {
|
144 |
-
"description": "School schedule (8 AM - 3 PM)",
|
145 |
-
"weekday": [0.1, 0.1, 0.1, 0.1, 0.2, 0.5, 0.9, 1.0, 1.0, 1.0, 1.0, 1.0,
|
146 |
-
0.8, 0.7, 0.4, 0.2, 0.1] + [0.1]*7,
|
147 |
-
"weekend": [0.05] * 24
|
148 |
-
},
|
149 |
-
"healthcare": {
|
150 |
-
"description": "24/7 full operation (hospitals)",
|
151 |
-
"weekday": [1.0] * 24,
|
152 |
-
"weekend": [1.0] * 24
|
153 |
-
},
|
154 |
-
"assembly": {
|
155 |
-
"description": "Intermittent use with afternoon and evening peak",
|
156 |
-
"weekday": [0.05]*8 + [0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.0, 0.8, 0.5] + [0.3, 0.2, 0.1, 0.1],
|
157 |
-
"weekend": [0.1]*8 + [0.3, 0.5, 0.6, 0.7, 0.8, 1.0, 1.0, 1.0, 0.8, 0.5] + [0.4, 0.3, 0.2, 0.1]
|
158 |
-
},
|
159 |
-
"industrial": {
|
160 |
-
"description": "Two shifts (6 AM - 10 PM)",
|
161 |
-
"weekday": [0.1]*5 + [0.6, 0.8, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
|
162 |
-
1.0, 1.0, 0.8, 0.6] + [0.4, 0.3, 0.2, 0.1, 0.1],
|
163 |
-
"weekend": [0.1]*6 + [0.4]*8 + [0.2]*10
|
164 |
-
},
|
165 |
-
"public_institutional": {
|
166 |
-
"description": "Standard institutional hours (8 AM - 6 PM)",
|
167 |
-
"weekday": [0.1]*6 + [0.5, 0.8, 1.0, 1.0, 1.0, 1.0, 0.8, 0.7,
|
168 |
-
0.5, 0.3] + [0.2]*8,
|
169 |
-
"weekend": [0.1]*24
|
170 |
-
},
|
171 |
-
"lodging": {
|
172 |
-
"description": "Lodging facilities (moderate usage all day)",
|
173 |
-
"weekday": [0.6]*6 + [0.7]*6 + [0.8]*6 + [0.9]*6,
|
174 |
-
"weekend": [0.7]*6 + [0.8]*6 + [0.9]*6 + [1.0]*6
|
175 |
-
},
|
176 |
-
"transport": {
|
177 |
-
"description": "Transport hubs (early start, taper late night)",
|
178 |
-
"weekday": [0.3, 0.4, 0.6, 0.8, 1.0, 1.0, 0.9, 0.9, 0.8, 0.7,
|
179 |
-
0.6, 0.6, 0.5, 0.5, 0.6, 0.7, 0.8, 1.0, 0.8, 0.6,
|
180 |
-
0.5, 0.4, 0.3, 0.2],
|
181 |
-
"weekend": [0.2, 0.3, 0.4, 0.6, 0.8, 0.8, 0.7, 0.7, 0.6, 0.6,
|
182 |
-
0.5, 0.5, 0.6, 0.7, 0.8, 0.9, 0.9, 1.0, 0.8, 0.6,
|
183 |
-
0.4, 0.3, 0.2, 0.1]
|
184 |
-
},
|
185 |
-
"continuous": {
|
186 |
-
"description": "Continuous operation 24/7 (e.g., data centre)",
|
187 |
-
"weekday": [1.0] * 24,
|
188 |
-
"weekend": [1.0] * 24
|
189 |
-
},
|
190 |
-
"custom": {
|
191 |
-
"description": "Custom schedule – user-defined",
|
192 |
-
"weekday": [0.0] * 24,
|
193 |
-
"weekend": [0.0] * 24
|
194 |
-
}
|
195 |
-
}
|
196 |
-
|
197 |
def display_internal_loads_page():
|
198 |
"""
|
199 |
Display the internal loads page.
|
@@ -1501,82 +1337,4 @@ def display_schedules_table(schedules: Dict[str, Any]):
|
|
1501 |
st.session_state.module_rerun_flags["internal_loads"] = True
|
1502 |
st.rerun()
|
1503 |
else:
|
1504 |
-
st.write("(Default)")
|
1505 |
-
|
1506 |
-
def display_schedule_chart(schedule_name: str, schedule_data: Dict[str, Any]):
|
1507 |
-
"""Display a chart for the given schedule."""
|
1508 |
-
hours = list(range(24))
|
1509 |
-
weekday_values = schedule_data.get("weekday", [0.0] * 24)
|
1510 |
-
weekend_values = schedule_data.get("weekend", [0.0] * 24)
|
1511 |
-
|
1512 |
-
fig = go.Figure()
|
1513 |
-
|
1514 |
-
fig.add_trace(go.Scatter(
|
1515 |
-
x=hours,
|
1516 |
-
y=weekday_values,
|
1517 |
-
mode='lines+markers',
|
1518 |
-
name='Weekday',
|
1519 |
-
line=dict(color='blue')
|
1520 |
-
))
|
1521 |
-
|
1522 |
-
fig.add_trace(go.Scatter(
|
1523 |
-
x=hours,
|
1524 |
-
y=weekend_values,
|
1525 |
-
mode='lines+markers',
|
1526 |
-
name='Weekend',
|
1527 |
-
line=dict(color='red')
|
1528 |
-
))
|
1529 |
-
|
1530 |
-
fig.update_layout(
|
1531 |
-
title=f"Schedule: {schedule_name}",
|
1532 |
-
xaxis_title="Hour of Day",
|
1533 |
-
yaxis_title="Fraction (0.0 - 1.0)",
|
1534 |
-
xaxis=dict(tickmode='linear', tick0=0, dtick=2),
|
1535 |
-
yaxis=dict(range=[0, 1.1]),
|
1536 |
-
height=400
|
1537 |
-
)
|
1538 |
-
|
1539 |
-
st.plotly_chart(fig, use_container_width=True)
|
1540 |
-
|
1541 |
-
def display_internal_loads_help():
|
1542 |
-
"""Display help information for the internal loads page."""
|
1543 |
-
st.markdown("""
|
1544 |
-
### Internal Loads Help
|
1545 |
-
|
1546 |
-
This page allows you to define internal heat gains from various sources within the building.
|
1547 |
-
|
1548 |
-
#### People
|
1549 |
-
- Define occupancy groups with different activity levels
|
1550 |
-
- Activity levels determine metabolic heat generation
|
1551 |
-
- Clothing insulation affects comfort calculations
|
1552 |
-
- Schedules control when people are present
|
1553 |
-
|
1554 |
-
#### Lighting
|
1555 |
-
- Define lighting systems with power density
|
1556 |
-
- Heat distribution between radiative and convective components
|
1557 |
-
- Schedules control lighting operation
|
1558 |
-
|
1559 |
-
#### Equipment
|
1560 |
-
- Define equipment heat gains (computers, appliances, etc.)
|
1561 |
-
- Separate sensible and latent heat gains
|
1562 |
-
- Heat distribution between radiative and convective components
|
1563 |
-
|
1564 |
-
#### Ventilation & Infiltration
|
1565 |
-
- **Ventilation**: Controlled outdoor air introduction
|
1566 |
-
- **Infiltration**: Uncontrolled air leakage
|
1567 |
-
- Rates based on building type and design standards
|
1568 |
-
|
1569 |
-
#### Schedules
|
1570 |
-
- Define hourly operation profiles (0.0 = off, 1.0 = full operation)
|
1571 |
-
- Separate weekday and weekend schedules
|
1572 |
-
- Templates available for common building types
|
1573 |
-
- Custom schedules can be created for specific needs
|
1574 |
-
|
1575 |
-
#### Usage Tips
|
1576 |
-
1. Start with building type defaults and adjust as needed
|
1577 |
-
2. Create realistic schedules based on actual building operation
|
1578 |
-
3. Consider diversity factors for large buildings
|
1579 |
-
4. Validate total loads against design expectations
|
1580 |
-
""")
|
1581 |
-
|
1582 |
-
#
|
|
|
20 |
import plotly.graph_objects as go
|
21 |
import plotly.express as px
|
22 |
from typing import Dict, List, Any, Optional, Tuple, Union
|
23 |
+
# Import data from i_l_data.py
|
24 |
+
from app.i_l_data import PEOPLE_ACTIVITY_LEVELS, DEFAULT_BUILDING_INTERNALS, DEFAULT_SCHEDULE_TEMPLATES, display_internal_loads_help
|
25 |
|
26 |
# Configure logging
|
27 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
|
30 |
# Define constants
|
31 |
LOAD_TYPES = ["People", "Lighting", "Equipment", "Ventilation & Infiltration", "Schedules"]
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
def display_internal_loads_page():
|
34 |
"""
|
35 |
Display the internal loads page.
|
|
|
1337 |
st.session_state.module_rerun_flags["internal_loads"] = True
|
1338 |
st.rerun()
|
1339 |
else:
|
1340 |
+
st.write("(Default)")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|