03chrisk commited on
Commit
09a9428
·
1 Parent(s): 9a60023

updating user dashboard with major quality of life changes

Browse files
streamlit_src/controllers/admin_controller.py CHANGED
@@ -1,5 +1,6 @@
1
  from models.air_quality_model import AirQualityModel
2
  from views.admin_view import AdminView
 
3
 
4
 
5
  class AdminController:
@@ -8,25 +9,33 @@ class AdminController:
8
  self.view = AdminView()
9
 
10
  def show_dashboard(self):
11
- return
12
- # Get today's data and predictions
13
  today_data = self.model.get_today_data()
14
  next_three_days = self.model.next_three_day_predictions()
 
15
 
16
- # WHO Guidelines
17
  who_guidelines = {
18
  "Pollutant": ["NO2 (µg/m³)", "O3 (µg/m³)"],
19
  "WHO Guideline": [self.model.WHO_NO2_LEVEL, self.model.WHO_O3_LEVEL],
20
  }
21
 
22
- # Display current data and predictions
23
- self.view.show_current_data(today_data, who_guidelines)
24
- self.view.display_predictions(next_three_days)
25
 
26
- # Compare to WHO guidelines
27
- self.view.compare_to_who(
28
- today_data, self.model.WHO_NO2_LEVEL, self.model.WHO_O3_LEVEL
29
- )
 
 
 
 
 
 
 
 
 
30
 
31
  def welcome_back(self):
32
  self.view.welcome_back()
 
1
  from models.air_quality_model import AirQualityModel
2
  from views.admin_view import AdminView
3
+ import streamlit as st
4
 
5
 
6
  class AdminController:
 
9
  self.view = AdminView()
10
 
11
  def show_dashboard(self):
12
+ # Fetch today's data and the next three days' predictions from the model
 
13
  today_data = self.model.get_today_data()
14
  next_three_days = self.model.next_three_day_predictions()
15
+ #model_metrics = self.model.get_model_metrics()
16
 
17
+ # Define WHO guidelines for pollutant levels
18
  who_guidelines = {
19
  "Pollutant": ["NO2 (µg/m³)", "O3 (µg/m³)"],
20
  "WHO Guideline": [self.model.WHO_NO2_LEVEL, self.model.WHO_O3_LEVEL],
21
  }
22
 
23
+ # Define layout: main content on the left and additional information on the right
24
+ col_main, col_right = st.columns([0.7, 0.3])
 
25
 
26
+ # Main content in the left column
27
+ with col_main:
28
+ # Display current data and future predictions
29
+ self.view.show_current_data(today_data, who_guidelines)
30
+
31
+ # Display predictions line plot
32
+
33
+ self.view.display_predictions_lineplot(next_three_days, who_guidelines)
34
+
35
+ # Right column content for additional details or actions
36
+ with col_right:
37
+ st.markdown("### Model Performance")
38
+ #self.view.show_model_performance(model_metrics)
39
 
40
  def welcome_back(self):
41
  self.view.welcome_back()
streamlit_src/controllers/user_controller.py CHANGED
@@ -20,6 +20,7 @@ class UserController:
20
 
21
  # Display current data and predictions
22
  self.view.show_current_data(today_data, who_guidelines)
 
23
  plot_type = self.view.view_option_selection()
24
  if plot_type == "Line Plot":
25
  self.view.display_predictions_lineplot(next_three_days, who_guidelines)
@@ -30,3 +31,6 @@ class UserController:
30
  self.view.compare_to_who(
31
  today_data, self.model.WHO_NO2_LEVEL, self.model.WHO_O3_LEVEL
32
  )
 
 
 
 
20
 
21
  # Display current data and predictions
22
  self.view.show_current_data(today_data, who_guidelines)
23
+ self.view.raise_awareness_and_quiz(today_data, who_guidelines)
24
  plot_type = self.view.view_option_selection()
25
  if plot_type == "Line Plot":
26
  self.view.display_predictions_lineplot(next_three_days, who_guidelines)
 
31
  self.view.compare_to_who(
32
  today_data, self.model.WHO_NO2_LEVEL, self.model.WHO_O3_LEVEL
33
  )
34
+
35
+ # Print sources
36
+ self.view.print_sources()
streamlit_src/facts.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "facts": [
3
+ "Air pollution is now recognized as the biggest environmental threat to human health, responsible for millions of deaths and lost years of healthy life each year.",
4
+ "Air pollution significantly contributes to noncommunicable diseases (NCDs), such as heart disease, lung cancer, and respiratory diseases.",
5
+ "Despite improvements in air quality in high-income countries, air pollution has worsened in many low- and middle-income countries due to rapid urbanization and economic development.",
6
+ "The health burden from air pollution also brings a significant economic toll due to increased healthcare costs and lost productivity.",
7
+ "Since 1987, the WHO has been providing health-based air quality guidelines, influencing pollution control policies worldwide.",
8
+ "In 2015, the World Health Assembly called for stronger global efforts to protect people from air pollution.",
9
+ "Over the past 15 years, there has been a marked increase in scientific evidence showing the harmful effects of air pollution."
10
+ ]
11
+ }
12
+
streamlit_src/question.json ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "quiz": [
3
+ {
4
+ "question": "What is the biggest environmental threat to human health?",
5
+ "options": [
6
+ "Climate change",
7
+ "Deforestation",
8
+ "Air pollution",
9
+ "Water pollution"
10
+ ],
11
+ "answer": "Air pollution"
12
+ },
13
+ {
14
+ "question": "Which disease is NOT significantly contributed to by air pollution?",
15
+ "options": [
16
+ "Lung cancer",
17
+ "Heart disease",
18
+ "Diabetes",
19
+ "Respiratory diseases"
20
+ ],
21
+ "answer": "Diabetes"
22
+ },
23
+ {
24
+ "question": "Since what year has the WHO been providing health-based air quality guidelines?",
25
+ "options": [
26
+ "1980",
27
+ "1987",
28
+ "1995",
29
+ "2000"
30
+ ],
31
+ "answer": "1987"
32
+ },
33
+ {
34
+ "question": "What global health event in 2015 called for stronger efforts against air pollution?",
35
+ "options": [
36
+ "The Paris Agreement",
37
+ "The World Health Assembly",
38
+ "The United Nations Climate Summit",
39
+ "The Earth Summit"
40
+ ],
41
+ "answer": "The World Health Assembly"
42
+ },
43
+ {
44
+ "question": "What is a major economic impact of air pollution?",
45
+ "options": [
46
+ "Increased healthcare costs",
47
+ "Increased tourism",
48
+ "Higher employment rates",
49
+ "Lower energy costs"
50
+ ],
51
+ "answer": "Increased healthcare costs"
52
+ }
53
+ ]
54
+ }
55
+
streamlit_src/views/admin_view.py CHANGED
@@ -1,40 +1,75 @@
1
  # views/user_view.py
2
  import streamlit as st
3
  import pandas as pd
4
- from datetime import date
5
  import time
 
6
 
7
 
8
  class AdminView:
9
  def show_current_data(self, today_data, who_guidelines):
10
- return
11
- st.sidebar.markdown(
12
- f"ADMIN Today's Date: **{date.today().strftime('%B %d, %Y')}**"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  )
14
- st.sidebar.markdown("### Current Pollutant Concentrations")
15
- today_data_df = pd.DataFrame([today_data])
16
- st.sidebar.dataframe(today_data_df.style.hide(axis="index"))
17
-
18
- st.sidebar.markdown("### WHO Guidelines")
19
- who_guidelines_df = pd.DataFrame(who_guidelines)
20
- st.sidebar.dataframe(who_guidelines_df.style.hide(axis="index"))
21
-
22
- def display_predictions(self, next_three_days):
23
- return
24
- st.markdown("### Predictions for the Next 3 Days")
25
- st.line_chart(next_three_days.set_index("Day"))
26
-
27
- def compare_to_who(self, today_data, no2_level, o3_level):
28
- return
29
- if today_data["NO2 (µg/m³)"] > no2_level:
30
- st.sidebar.error("⚠️ NO2 levels are above WHO guidelines!")
31
- else:
32
- st.sidebar.success("✅ NO2 levels are within safe limits.")
33
-
34
- if today_data["O3 (µg/m³)"] > o3_level:
35
- st.sidebar.error("⚠️ O3 levels are above WHO guidelines!")
36
- else:
37
- st.sidebar.success("✅ O3 levels are within safe limits.")
38
 
39
  def welcome_back(self):
40
  st.empty()
 
1
  # views/user_view.py
2
  import streamlit as st
3
  import pandas as pd
4
+ from datetime import date, datetime, timedelta
5
  import time
6
+ import plotly.graph_objects as go
7
 
8
 
9
  class AdminView:
10
  def show_current_data(self, today_data, who_guidelines):
11
+ st.sidebar.markdown(f"Today's Date: **{datetime.now().strftime('%B %d, %Y')}**")
12
+
13
+ # Display today's pollutant data along with WHO guidelines
14
+ merged_data = {
15
+ "Pollutant": ["NO2 (µg/m³)", "O3 (µg/m³)"],
16
+ "Current Concentration": [
17
+ today_data["NO2 (µg/m³)"],
18
+ today_data["O3 (µg/m³)"],
19
+ ],
20
+ "WHO Guideline": [
21
+ who_guidelines["WHO Guideline"][0],
22
+ who_guidelines["WHO Guideline"][1],
23
+ ],
24
+ }
25
+ merged_data_df = pd.DataFrame(merged_data)
26
+ st.sidebar.markdown("### Current Pollutant Concentrations and WHO Guidelines")
27
+ st.sidebar.dataframe(merged_data_df, hide_index=True)
28
+
29
+ def show_model_performance(self, model_metrics):
30
+ st.markdown("### Model Performance Metrics")
31
+ for model, metrics in model_metrics.items():
32
+ st.markdown(f"**{model}**")
33
+ st.write(f"RMSE: {metrics['RMSE']}, MAE: {metrics['MAE']}")
34
+
35
+ def display_predictions_lineplot(self, next_three_days, who_guidelines):
36
+ tomorrow, day_after_tomorrow, two_days_after_tomorrow = self.get_next_three_days_dates()
37
+
38
+ # Update the dataframe with actual dates
39
+ next_three_days["Date"] = [tomorrow, day_after_tomorrow, two_days_after_tomorrow]
40
+
41
+ # Create line plot for the predictions
42
+ fig = go.Figure()
43
+ fig.add_trace(go.Scatter(x=next_three_days["Date"], y=next_three_days["NO2 (µg/m³)"], mode="lines+markers", name="NO2"))
44
+ fig.add_trace(go.Scatter(x=next_three_days["Date"], y=next_three_days["O3 (µg/m³)"], mode="lines+markers", name="O3"))
45
+
46
+ # Add WHO guidelines as reference lines
47
+ fig.add_hline(y=who_guidelines["WHO Guideline"][0], line_dash="dot", annotation_text="WHO NO2 Guideline")
48
+ fig.add_hline(y=who_guidelines["WHO Guideline"][1], line_dash="dot", annotation_text="WHO O3 Guideline")
49
+
50
+ # Update layout
51
+ fig.update_layout(
52
+ title="Pollutant Predictions for Next 3 Days",
53
+ xaxis_title="Date",
54
+ yaxis_title="Concentration (µg/m³)",
55
+ hovermode="x unified"
56
  )
57
+
58
+ st.plotly_chart(fig)
59
+
60
+ def display_model_comparisons(self, actual, predicted):
61
+ st.markdown("### Model Prediction Comparisons")
62
+ fig = go.Figure()
63
+ fig.add_trace(go.Scatter(x=actual, y=predicted, mode="markers", name="Predictions vs Actual"))
64
+ fig.update_layout(title="Actual vs Predicted Pollutant Levels", xaxis_title="Actual", yaxis_title="Predicted")
65
+ st.plotly_chart(fig)
66
+
67
+ def get_next_three_days_dates(self):
68
+ today = datetime.now()
69
+ tomorrow = today + timedelta(days=1)
70
+ day_after_tomorrow = today + timedelta(days=2)
71
+ two_days_after_tomorrow = today + timedelta(days=3)
72
+ return tomorrow, day_after_tomorrow, two_days_after_tomorrow
 
 
 
 
 
 
 
 
73
 
74
  def welcome_back(self):
75
  st.empty()
streamlit_src/views/user_view.py CHANGED
@@ -3,6 +3,13 @@ import streamlit as st
3
  import pandas as pd
4
  from datetime import date, datetime, timedelta
5
  import plotly.graph_objects as go
 
 
 
 
 
 
 
6
 
7
 
8
  class UserView:
@@ -29,6 +36,11 @@ class UserView:
29
  st.sidebar.dataframe(merged_data_df, hide_index=True)
30
 
31
  def get_next_three_days_dates(self):
 
 
 
 
 
32
  today = datetime.now() # Get the current date and time
33
  tomorrow = today + timedelta(days=1)
34
  day_after_tomorrow = today + timedelta(days=2)
@@ -36,8 +48,6 @@ class UserView:
36
  return tomorrow, day_after_tomorrow, two_days_after_tomorrow
37
 
38
  def display_predictions_lineplot(self, next_three_days, who_guidelines):
39
- st.markdown("### Predictions for the Next 3 Days")
40
-
41
  tomorrow, day_after_tomorrow, two_days_after_tomorrow = (
42
  self.get_next_three_days_dates()
43
  )
@@ -105,15 +115,19 @@ class UserView:
105
  # Display the plot in Streamlit
106
  st.plotly_chart(fig)
107
 
108
- def get_no2_color(self, value, who_limit):
109
- # Define the gradient points
110
- if value <= who_limit:
111
- # Blue -> Purple gradient
112
- return f"rgba({int(0 + (255 * value / who_limit))}, 0, 255, 1)" # Gradient from blue to purple
 
 
 
 
 
113
  else:
114
- # Purple -> Red gradient
115
- excess_value = min(who_limit, value - who_limit)
116
- return f"rgba(255, 0, {int(255 - (255 * excess_value / who_limit))}, 1)" # Gradient from purple to red
117
 
118
  def display_predictions_gaugeplot(self, next_three_days, who_guidelines):
119
  st.markdown("### Predictions for the Next 3 Days")
@@ -140,7 +154,7 @@ class UserView:
140
  with col1:
141
  # Get color based on NO2 value
142
  no2_value = next_three_days["NO2 (µg/m³)"][i]
143
- no2_color = self.get_no2_color(
144
  no2_value, who_guidelines["WHO Guideline"][0]
145
  )
146
  fig_no2 = go.Figure(
@@ -152,7 +166,7 @@ class UserView:
152
  "axis": {
153
  "range": [
154
  0,
155
- max(who_guidelines["WHO Guideline"][0], 100),
156
  ]
157
  },
158
  "bar": {"color": no2_color},
@@ -167,6 +181,10 @@ class UserView:
167
 
168
  # O3 Gauge
169
  with col2:
 
 
 
 
170
  fig_o3 = go.Figure(
171
  go.Indicator(
172
  mode="gauge+number",
@@ -176,10 +194,10 @@ class UserView:
176
  "axis": {
177
  "range": [
178
  0,
179
- max(who_guidelines["WHO Guideline"][1], 150),
180
  ]
181
  },
182
- "bar": {"color": "lightblue"},
183
  },
184
  domain={"x": [0, 1], "y": [0, 1]}, # Controls size
185
  )
@@ -190,8 +208,9 @@ class UserView:
190
  st.plotly_chart(fig_o3)
191
 
192
  def view_option_selection(self) -> str:
 
193
  plot_type = st.selectbox(
194
- "Choose Visualization Type", ("Line Plot", "Gauge Plot")
195
  )
196
  return plot_type
197
 
@@ -206,18 +225,96 @@ class UserView:
206
  else:
207
  st.sidebar.success("✅ O3 levels are within safe limits.")
208
 
209
- def raise_awareness(self):
210
- st.sidebar.markdown("""
211
- **Air pollution** is a serious concern that affects the environment and public health.
212
- High levels of pollutants, such as ozone (O₃) and nitrogen dioxide (NO₂), can lead to
213
- respiratory problems, aggravate pre-existing conditions like asthma, and contribute to
214
- cardiovascular diseases. On particularly bad days, vulnerable groups such as children,
215
- the elderly, and those with respiratory issues are at even greater risk.
216
- """)
217
-
218
- st.sidebar.markdown("""
219
- **Key Pollutants:**
220
- - **Ozone (O₃):** Formed by chemical reactions in the atmosphere, particularly on sunny days.
221
- - **Nitrogen Dioxide (NO₂):** Mostly emitted from vehicles and industrial activities, this can cause
222
- irritation of the respiratory system.
223
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import pandas as pd
4
  from datetime import date, datetime, timedelta
5
  import plotly.graph_objects as go
6
+ import json
7
+ import random
8
+ import sys
9
+ import os
10
+
11
+ FACTS_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "facts.json")
12
+ QUESTIONS_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "question.json")
13
 
14
 
15
  class UserView:
 
36
  st.sidebar.dataframe(merged_data_df, hide_index=True)
37
 
38
  def get_next_three_days_dates(self):
39
+ """
40
+ Returns the next three days' dates in datetime format as a tuple.
41
+
42
+ :return: tuple of three datetime objects, representing tomorrow, day after tomorrow, and two days after tomorrow.
43
+ """
44
  today = datetime.now() # Get the current date and time
45
  tomorrow = today + timedelta(days=1)
46
  day_after_tomorrow = today + timedelta(days=2)
 
48
  return tomorrow, day_after_tomorrow, two_days_after_tomorrow
49
 
50
  def display_predictions_lineplot(self, next_three_days, who_guidelines):
 
 
51
  tomorrow, day_after_tomorrow, two_days_after_tomorrow = (
52
  self.get_next_three_days_dates()
53
  )
 
115
  # Display the plot in Streamlit
116
  st.plotly_chart(fig)
117
 
118
+ def get_color(self, value, who_limit):
119
+ half_who_limit = who_limit / 2
120
+
121
+ if value <= half_who_limit:
122
+ # Green -> Yellow gradient
123
+ return f"rgba({int(255 * value / half_who_limit)}, 255, 0, 1)" # Gradient from green to yellow
124
+ elif value <= who_limit:
125
+ # Yellow -> Red gradient
126
+ excess_value = value - half_who_limit
127
+ return f"rgba(255, {int(255 - (255 * excess_value / half_who_limit))}, 0, 1)" # Gradient from yellow to red
128
  else:
129
+ # Beyond the WHO limit, fully red
130
+ return "rgba(255, 0, 0, 1)" # Fully red
 
131
 
132
  def display_predictions_gaugeplot(self, next_three_days, who_guidelines):
133
  st.markdown("### Predictions for the Next 3 Days")
 
154
  with col1:
155
  # Get color based on NO2 value
156
  no2_value = next_three_days["NO2 (µg/m³)"][i]
157
+ no2_color = self.get_color(
158
  no2_value, who_guidelines["WHO Guideline"][0]
159
  )
160
  fig_no2 = go.Figure(
 
166
  "axis": {
167
  "range": [
168
  0,
169
+ 2*who_guidelines["WHO Guideline"][0],
170
  ]
171
  },
172
  "bar": {"color": no2_color},
 
181
 
182
  # O3 Gauge
183
  with col2:
184
+ o3_value = next_three_days["O3 (µg/m³)"][i]
185
+ o3_color = self.get_color(
186
+ o3_value, who_guidelines["WHO Guideline"][1]
187
+ )
188
  fig_o3 = go.Figure(
189
  go.Indicator(
190
  mode="gauge+number",
 
194
  "axis": {
195
  "range": [
196
  0,
197
+ 1.5*who_guidelines["WHO Guideline"][1],
198
  ]
199
  },
200
+ "bar": {"color": o3_color},
201
  },
202
  domain={"x": [0, 1], "y": [0, 1]}, # Controls size
203
  )
 
208
  st.plotly_chart(fig_o3)
209
 
210
  def view_option_selection(self) -> str:
211
+ st.markdown("### Visualizing Air Quality Predictions")
212
  plot_type = st.selectbox(
213
+ "", ("Line Plot", "Gauge Plot")
214
  )
215
  return plot_type
216
 
 
225
  else:
226
  st.sidebar.success("✅ O3 levels are within safe limits.")
227
 
228
+ def raise_awareness(self, today_data, who_guidelines):
229
+ st.markdown("### Air Quality Awareness")
230
+
231
+ # Load facts from the JSON file
232
+ with open(FACTS_PATH, 'r') as f:
233
+ facts = json.load(f)["facts"]
234
+
235
+ # Randomly select a fact from the list
236
+ random_fact = random.choice(facts)
237
+
238
+ # Create expandable sections for key pollutant information
239
+ with st.expander("🌍 What is Air Pollution?"):
240
+ st.write("""
241
+ **Air pollution** is a serious concern that affects the environment and public health.
242
+ High levels of pollutants, such as ozone (O₃) and nitrogen dioxide (NO₂), can lead to
243
+ respiratory problems, aggravate pre-existing conditions like asthma, and contribute to
244
+ cardiovascular diseases.
245
+ """)
246
+
247
+ with st.expander("⚠️ Why O₃ and NO₂ Matter"):
248
+ st.write("""
249
+ **Ozone (O₃):** Formed by chemical reactions in the atmosphere, particularly on sunny days.
250
+ High levels can cause chest pain, coughing, throat irritation, and airway inflammation.
251
+
252
+ **Nitrogen Dioxide (NO₂):** Mostly emitted from vehicles and industrial activities, this can cause
253
+ irritation of the respiratory system and decrease lung function, especially during long-term exposure.
254
+ """)
255
+
256
+ self.add_spaces(num_lines=3)
257
+
258
+ # Display the random fact for user awareness
259
+ st.markdown("### Did You Know?")
260
+ st.info(random_fact) # Display the random fact in an info box
261
+
262
+ self.add_spaces(num_lines=3)
263
+
264
+ # Show real-time suggestions for high pollution days
265
+ st.markdown("### Health Recommendations Based on Current Levels")
266
+ if today_data["NO2 (µg/m³)"] > who_guidelines["WHO Guideline"][0] or today_data["O3 (µg/m³)"] > who_guidelines["WHO Guideline"][1]:
267
+ st.error("🚨 High pollution levels today. Avoid outdoor activities if possible, especially for vulnerable groups.")
268
+ else:
269
+ st.success("✅ Air quality is within safe limits today. Enjoy your outdoor activities!")
270
+
271
+ self.add_spaces(num_lines=3)
272
+
273
+ def print_sources(self):
274
+ # Provide user links to external resources or reports
275
+ st.markdown("### Learn More")
276
+ st.markdown("[WHO Air Quality Guidelines](https://www.who.int/news-room/fact-sheets/detail/ambient-(outdoor)-air-quality-and-health)")
277
+ st.markdown("[Air Pollution Facts](https://www.un.org/sustainabledevelopment/air-pollution/)")
278
+
279
+ def quiz(self):
280
+ with open(QUESTIONS_PATH, 'r') as f:
281
+ quiz_data = json.load(f)
282
+ # Access the quiz questions
283
+ questions = quiz_data['quiz']
284
+ random_question = random.choice(questions)
285
+
286
+ # Add a simple quiz to engage the user
287
+ st.markdown("### Quick Quiz: How Much Do You Know About Air Pollution?")
288
+ with st.form(key="quiz_form"):
289
+ # Display the first question and options
290
+ st.write(random_question['question'])
291
+ options = random_question['options']
292
+ answer = st.radio("Choose an option:", options)
293
+ submitted = st.form_submit_button("Submit Answer")
294
+
295
+ if submitted:
296
+ if answer == random_question['answer']:
297
+ st.success("Correct!")
298
+ else:
299
+ st.error("Incorrect. The correct answer is: " + random_question['answer'])
300
+
301
+ def raise_awareness_and_quiz(self, today_data, who_guidelines):
302
+ # Create two columns: main column for awareness and right column for the quiz
303
+ col_main, col_right = st.columns([0.7, 0.3], gap="large") # 70% for awareness, 30% for quiz
304
+
305
+ # Left column: Raise awareness
306
+ with col_main:
307
+ self.raise_awareness(today_data, who_guidelines)
308
+
309
+ # Right column: Quiz
310
+ with col_right:
311
+ self.quiz()
312
+
313
+ def add_spaces(self, num_lines=1):
314
+ """Add vertical space between sections by adding empty lines.
315
+
316
+ Args:
317
+ num_lines (int): Number of blank lines to add. Default is 1.
318
+ """
319
+ for _ in range(num_lines):
320
+ st.write("") # This adds a blank line to create space