JAMESPARK3 commited on
Commit
fb2d724
ยท
verified ยท
1 Parent(s): d9551ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -139
app.py CHANGED
@@ -178,41 +178,21 @@ def get_korean_weekday(date):
178
  }
179
  return weekday_dict[weekday]
180
 
181
- # ์„ธ์…˜ ์ดˆ๊ธฐํ™”
182
- if 'last_weather_data' not in st.session_state:
183
- st.session_state.last_weather_data = None
184
- st.session_state.last_successful_update = None
185
- st.session_state.last_forecast_message = None
186
- st.session_state.data_initialized = False
187
-
188
  @st.cache_data(ttl=300) # 5๋ถ„๋งˆ๋‹ค ์บ์‹œ ๊ฐฑ์‹ 
189
  def get_weather_data():
190
  url = "http://openapi.seoul.go.kr:8088/77544e69764a414d363647424a655a/xml/citydata/1/5/์‹ ๋ฆผ์—ญ"
191
  try:
192
- response = requests.get(url, timeout=5)
193
- response.raise_for_status()
194
- if not response.text.strip():
195
  raise ValueError("์‘๋‹ต์ด ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค.")
196
  data = xmltodict.parse(response.text)
197
- weather_data = data['SeoulRtd.citydata']['CITYDATA']['WEATHER_STTS']['WEATHER_STTS']
198
-
199
- # ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜จ ๊ฒฝ์šฐ ์„ธ์…˜ ์ƒํƒœ์— ์ €์žฅ
200
- st.session_state.last_weather_data = weather_data
201
- st.session_state.last_successful_update = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
202
- st.session_state.data_initialized = True
203
- return weather_data
204
-
205
- except (requests.exceptions.RequestException, ValueError, KeyError) as e:
206
- if not st.session_state.data_initialized:
207
- st.error("๋‚ ์”จ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”.")
208
- return None
209
-
210
- st.warning("๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ๋ถˆ์•ˆ์ •ํ•˜์—ฌ ์ด์ „ ๋‚ ์”จ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.")
211
- if st.session_state.last_weather_data is not None:
212
- last_update = st.session_state.last_successful_update or "์•Œ ์ˆ˜ ์—†์Œ"
213
- st.info(f"๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ: {last_update}")
214
- return st.session_state.last_weather_data
215
- return None
216
 
217
  def get_background_color(pm10_value):
218
  try:
@@ -405,7 +385,7 @@ def show_weather_info(data):
405
  st.markdown(f'''
406
  <div class="time-container">
407
  <div style="text-align: center; margin-bottom: 0.5rem; font-size: 6em; font-weight: bold; color: black;">
408
- {temp}<span style="font-size: 1.2em; vertical-align: middle; color: white; text-shadow: 1px 1px 2px rgba(0,0,0,0.3);">{precip_mark}</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {tomorrow_morning_weather}
409
  </div>
410
  <span class="date-text">{formatted_date}</span>
411
  </div>
@@ -440,61 +420,6 @@ def show_weather_info(data):
440
  st.markdown('</div>', unsafe_allow_html=True)
441
 
442
 
443
- def get_forecast_message(current_time, forecast_data_str):
444
- try:
445
- # ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ํ™•์ธ
446
- try:
447
- requests.get("https://glhf.chat", timeout=3)
448
- except:
449
- if st.session_state.last_forecast_message:
450
- st.warning("๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ๋ถˆ์•ˆ์ •ํ•˜์—ฌ ์ด์ „ ๋‚ ์”จ ์˜ˆ๋ณด๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.")
451
- return st.session_state.last_forecast_message
452
- return "ํ˜„์žฌ ๋‚ ์”จ ์˜ˆ๋ณด ์ƒ์„ฑ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
453
-
454
- client = OpenAI(
455
- api_key="glhf_9ea0e0babe1e45353dd03b44cb979e22",
456
- base_url="https://glhf.chat/api/openai/v1",
457
- http_client=httpx.Client(
458
- follow_redirects=True,
459
- timeout=30.0
460
- )
461
- )
462
-
463
- response = client.chat.completions.create(
464
- model="hf:Nexusflow/Athene-V2-Chat",
465
- messages=[
466
- {"role": "system", "content": "๋‹น์‹ ์€ ๋‚ ์”จ ์˜ˆ๋ณด๊ด€์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์‹œ๊ฐ„๋Œ€๋ณ„ ๋‚ ์”จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ •ํ™•ํ•œ ๋‚ ์”จ ์˜ˆ๋ณด๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. FCST_DT์˜ ์‹œ๊ฐ„์€ 24์‹œ๊ฐ„์ œ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค (์˜ˆ: 1900์€ ์ €๋… 7์‹œ์ž…๋‹ˆ๋‹ค)."},
467
- {"role": "user", "content": f"""ํ˜„์žฌ ์‹œ๊ฐ์€ {current_time.strftime('%H์‹œ %M๋ถ„')}์ž…๋‹ˆ๋‹ค.
468
-
469
- ๋‹ค์Œ FCST_DT์˜ ์‹œ๊ฐ„๋Œ€๋ณ„ ๋‚ ์”จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ณ  ์‹ค์ œ ๋‚ ์”จ ์ƒํ™ฉ์— ๋งž๋Š” ์ •ํ™•ํ•œ ๋‚ ์”จ ์˜ˆ๋ณด๋ฅผ 200์ž์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. ๋น„๋‚˜ ๋ˆˆ ์˜ˆ๋ณด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์šฐ์‚ฐ์„ ์ค€๋น„ํ•˜๋„๋ก ์•ˆ๋‚ดํ•ด์ฃผ์„ธ์š”. ์˜ท์ฐจ๋ฆผ์€ ๋‹ค์Œ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
470
- 27ยฐC์ด์ƒ: ๋ฐ˜ํŒ”ํ‹ฐ, ๋ฐ˜๏ฟฝ๏ฟฝ์ง€, ๋ฏผ์†Œ๋งค
471
- 23ยฐC~26ยฐC: ์–‡์€ ์…”์ธ , ๋ฐ˜๋ฐ”์ง€
472
- 20ยฐC~22ยฐC: ์–‡์€ ๊ฐ€๋””๊ฑด, ๊ธดํŒ”
473
- 17ยฐC~19ยฐC: ์–‡์€ ๋‹ˆํŠธ, ๋งจํˆฌ๋งจ, ๊ธด๋ฐ”์ง€
474
- 12ยฐC~16ยฐC: ์ž์ผ“, ๊ฐ€๋””๊ฑด, ๊ธด๋ฐ”์ง€
475
- 9ยฐC~11ยฐC: ํŠธ๋ Œ์น˜์ฝ”ํŠธ, ์•ผ์ƒ, ๊ธฐ๋ชจ๋ฐ”์ง€
476
- 5ยฐC~8ยฐC: ์ฝ”ํŠธ, ๊ฐ€์ฃฝ์ž์ผ“, ๋‹ˆํŠธ
477
- 4ยฐC ์ดํ•˜: ํŒจ๋”ฉ, ๋‘๊บผ์šด ์ฝ”ํŠธ, ๋ชฉ๋„๋ฆฌ
478
-
479
- {forecast_data_str}"""}
480
- ],
481
- temperature=0.7,
482
- max_tokens=500,
483
- top_p=0.8,
484
- frequency_penalty=0,
485
- presence_penalty=0
486
- )
487
- message = response.choices[0].message.content
488
- st.session_state.last_forecast_message = message
489
- return message
490
-
491
- except Exception as e:
492
- if st.session_state.last_forecast_message:
493
- st.warning("๋‚ ์”จ ์˜ˆ๋ณด ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ „ ์˜ˆ๋ณด๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.")
494
- return st.session_state.last_forecast_message
495
- return "ํ˜„์žฌ ๋‚ ์”จ ์˜ˆ๋ณด ์ƒ์„ฑ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
496
-
497
-
498
  def show_temperature_graph(data):
499
  st.markdown('<div class="section-container">', unsafe_allow_html=True)
500
  st.markdown('<h1 style="text-align: center; margin-bottom: 1rem;">์‹œ๊ฐ„๋Œ€๋ณ„ ์˜จ๋„</h1>', unsafe_allow_html=True)
@@ -672,7 +597,7 @@ def show_temperature_graph(data):
672
  y=max(temps) + 3,
673
  text=f"{icon}",
674
  showarrow=False,
675
- font=dict(size=30, color="white")
676
  )
677
  fig.add_annotation(
678
  x=times[i],
@@ -723,64 +648,61 @@ def show_temperature_graph(data):
723
 
724
  st.plotly_chart(fig, use_container_width=True)
725
 
726
- # ํ˜„์žฌ ์‹œ๊ฐ„๊ณผ ์˜ˆ๋ณด ์‹œ๊ฐ„ ์ •๋ณด ์ถ”๊ฐ€
727
- current_time = datetime.utcnow() + timedelta(hours=9)
728
- current_date_str = current_time.strftime('%Y๋…„ %m์›” %d์ผ')
729
- tomorrow_date_str = (current_time + timedelta(days=1)).strftime('%Y๋…„ %m์›” %d์ผ')
 
 
 
 
 
 
730
 
731
- forecast_data_str = "\n".join([
732
- f"[{f['FCST_DT'][:4]}๋…„ {f['FCST_DT'][4:6]}์›” {f['FCST_DT'][6:8]}์ผ {f['FCST_DT'][8:10]}์‹œ] {temp}๋„, {description}"
733
- for f, time, temp, description in zip(valid_forecast_data, times, temps, weather_descriptions)
734
- ])
735
 
736
- # OpenAI API ํ˜ธ์ถœ์„ ๋ณ„๋„ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์—๋Ÿฌ ์ฒ˜๋ฆฌ
737
- forecast_message = get_forecast_message(current_time, forecast_data_str)
738
-
739
- # ๋‚ ์”จ ์˜ˆ๋ณด ๋ฉ”์‹œ์ง€ ํ‘œ์‹œ
740
- st.markdown(
741
- f"""
742
- <style>
743
- .moving-text-container {{
744
- width: 100%;
745
- overflow: hidden;
746
- background-color: rgba(255, 255, 255, 0.9);
747
- padding: 15px 0;
748
- margin: 20px 0;
749
- border-radius: 10px;
750
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
751
- }}
752
-
753
- .moving-text {{
754
- display: inline-block;
755
- white-space: nowrap;
756
- animation: moveText 30s linear infinite;
757
- padding-left: 100%;
758
- font-size: 1.7rem;
759
- font-weight: 600;
760
- color: #1f1f1f;
761
- }}
762
-
763
- @keyframes moveText {{
764
- 0% {{ transform: translateX(0); }}
765
- 100% {{ transform: translateX(-100%); }}
766
- }}
767
- </style>
768
- <div class="moving-text-container">
769
- <div class="moving-text">
770
- {forecast_message}
771
- </div>
 
772
  </div>
773
- """,
774
- unsafe_allow_html=True
775
- )
776
 
777
  # ์Šคํฌ๋กค ํ…์ŠคํŠธ ์œ„์— ๋ฒ„ํŠผ์ด ์˜ค๋„๋ก ๋งˆ์ง„ ์ถ”๊ฐ€
778
  st.markdown('''
779
- <style>
780
- div.stButton > button {
781
- margin-top: 2rem;
782
- }
783
- </style>
784
  ''', unsafe_allow_html=True)
785
 
786
  # ์šฐ๋ฆฌ์ง‘ ๋‚ ์”จ ์ •๋ณด๋กœ ๋Œ์•„๊ฐ€๊ธฐ ๋ฒ„ํŠผ ์ถ”๊ฐ€
@@ -788,7 +710,6 @@ def show_temperature_graph(data):
788
 
789
  st.markdown('</div>', unsafe_allow_html=True)
790
 
791
-
792
  def main():
793
  if 'current_section' not in st.session_state:
794
  st.session_state.current_section = 'weather'
 
178
  }
179
  return weekday_dict[weekday]
180
 
 
 
 
 
 
 
 
181
  @st.cache_data(ttl=300) # 5๋ถ„๋งˆ๋‹ค ์บ์‹œ ๊ฐฑ์‹ 
182
  def get_weather_data():
183
  url = "http://openapi.seoul.go.kr:8088/77544e69764a414d363647424a655a/xml/citydata/1/5/์‹ ๋ฆผ์—ญ"
184
  try:
185
+ response = requests.get(url)
186
+ response.raise_for_status() # HTTPError์— ๋Œ€ํ•ด ์˜ˆ์™ธ ๋ฐœ์ƒ
187
+ if not response.text.strip(): # ๋นˆ ์‘๋‹ต ์ฒ˜๋ฆฌ
188
  raise ValueError("์‘๋‹ต์ด ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค.")
189
  data = xmltodict.parse(response.text)
190
+ return data['SeoulRtd.citydata']['CITYDATA']['WEATHER_STTS']['WEATHER_STTS']
191
+ except requests.exceptions.RequestException as e:
192
+ st.error(f"API ํ˜ธ์ถœ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
193
+ except Exception as e:
194
+ st.error(f"๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
195
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
  def get_background_color(pm10_value):
198
  try:
 
385
  st.markdown(f'''
386
  <div class="time-container">
387
  <div style="text-align: center; margin-bottom: 0.5rem; font-size: 6em; font-weight: bold; color: black;">
388
+ {temp}{precip_mark} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {tomorrow_morning_weather}
389
  </div>
390
  <span class="date-text">{formatted_date}</span>
391
  </div>
 
420
  st.markdown('</div>', unsafe_allow_html=True)
421
 
422
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  def show_temperature_graph(data):
424
  st.markdown('<div class="section-container">', unsafe_allow_html=True)
425
  st.markdown('<h1 style="text-align: center; margin-bottom: 1rem;">์‹œ๊ฐ„๋Œ€๋ณ„ ์˜จ๋„</h1>', unsafe_allow_html=True)
 
597
  y=max(temps) + 3,
598
  text=f"{icon}",
599
  showarrow=False,
600
+ font=dict(size=30)
601
  )
602
  fig.add_annotation(
603
  x=times[i],
 
648
 
649
  st.plotly_chart(fig, use_container_width=True)
650
 
651
+ # ๋‚ ์”จ ์˜ˆ๋ณด ์ƒ์„ฑ ๋ฐ ํ‘œ์‹œ ๋ถ€๋ถ„์„ ์„ธ์…˜ ์ƒํƒœ๋กœ ๊ด€๋ฆฌ
652
+ if 'weather_forecast' not in st.session_state:
653
+ client = OpenAI(
654
+ api_key="glhf_9ea0e0babe1e45353dd03b44cb979e22",
655
+ base_url="https://glhf.chat/api/openai/v1",
656
+ http_client=httpx.Client(
657
+ follow_redirects=True,
658
+ timeout=30.0
659
+ )
660
+ )
661
 
 
 
 
 
662
 
663
+ # ํ˜„์žฌ ์‹œ๊ฐ„๊ณผ ์˜ˆ๋ณด ์‹œ๊ฐ„ ์ •๋ณด ์ถ”๊ฐ€
664
+ current_time = datetime.utcnow() + timedelta(hours=9)
665
+ current_date_str = current_time.strftime('%Y๋…„ %m์›” %d์ผ')
666
+ tomorrow_date_str = (current_time + timedelta(days=1)).strftime('%Y๋…„ %m์›” %d์ผ')
667
+
668
+ forecast_data_str = "\n".join([
669
+ f"[{f['FCST_DT'][:4]}๋…„ {f['FCST_DT'][4:6]}์›” {f['FCST_DT'][6:8]}์ผ {f['FCST_DT'][8:10]}์‹œ] {temp}๋„, {description}"
670
+ for f, time, temp, description in zip(valid_forecast_data, times, temps, weather_descriptions)
671
+ ])
672
+
673
+ response = client.chat.completions.create(
674
+ model="hf:Nexusflow/Athene-V2-Chat",
675
+ messages=[
676
+ {"role": "system", "content": "๋‹น์‹ ์€ ๋‚ ์”จ ์˜ˆ๋ณด๊ด€์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์‹œ๊ฐ„๋Œ€๋ณ„ ๋‚ ์”จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ •ํ™•ํ•œ ๋‚ ์”จ ์˜ˆ๋ณด๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."},
677
+ {"role": "user", "content": f"""ํ˜„์žฌ ์‹œ๊ฐ์€ {current_time.strftime('%H์‹œ %M๋ถ„')}์ž…๋‹ˆ๋‹ค.
678
+
679
+ ๋‹ค์Œ FCST_DT์˜ ์‹œ๊ฐ„๋Œ€๋ณ„ ๋‚ ์”จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ณ  ์‹ค์ œ ๋‚ ์”จ ์ƒํ™ฉ์— ๋งž๋Š” ์ •ํ™•ํ•œ ๋‚ ์”จ ์˜ˆ๋ณด๋ฅผ 200์ž์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ๋ฌธ์žฅ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”. ๋น„๋‚˜ ๋ˆˆ ์˜ˆ๋ณด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์šฐ์‚ฐ์„ ์ค€๋น„ํ•˜๋„๋ก ์•ˆ๋‚ดํ•ด์ฃผ์„ธ์š”. ์˜ท์ฐจ๋ฆผ์€ ๋‹ค์Œ์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.
680
+ 27ยฐC์ด์ƒ: ๋ฐ˜ํŒ”ํ‹ฐ, ๋ฐ˜๋ฐ”์ง€, ๋ฏผ์†Œ๋งค
681
+ 23ยฐC~26ยฐC: ์–‡์€ ์…”์ธ , ๋ฐ˜ํŒ”ํ‹ฐ, ๋ฐ˜๋ฐ”์ง€, ๋ฉด๋ฐ”์ง€
682
+ 20ยฐC~22ยฐC: ์–‡์€ ๊ฐ€๋””๊ฑด, ๊ธดํŒ”ํ‹ฐ, ๊ธด๋ฐ”์ง€
683
+ 17ยฐC~19ยฐC: ์–‡์€ ๋‹ˆํŠธ, ๊ฐ€๋””๊ฑด, ๋งจํˆฌ๋งจ, ์–‡์€ ์ž์ผ“, ๊ธด๋ฐ”์ง€
684
+ 12ยฐC~16ยฐC: ์ž์ผ“, ๊ฐ€๋””๊ฑด, ์•ผ์ƒ, ๋งจํˆฌ๋งจ, ๋‹ˆํŠธ, ์Šคํƒ€ํ‚น, ๊ธด๋ฐ”์ง€
685
+ 9ยฐC~11ยฐC: ํŠธ๋ Œ์น˜์ฝ”ํŠธ, ์•ผ์ƒ, ๊ฐ€์ฃฝ ์ž์ผ“, ์Šคํƒ€ํ‚น, ๊ธด๋ฐ”์ง€
686
+ 5ยฐC~8ยฐC: ์ฝ”ํŠธ, ํžˆํŠธํ…, ๋‹ˆํŠธ, ๊ธด๋ฐ”์ง€
687
+ 4ยฐC์ดํ•˜: ํŒจ๋”ฉ, ๋‘๊บผ์šด ์ฝ”ํŠธ, ๋ชฉ๋„๋ฆฌ, ๊ธฐ๋ชจ์ œํ’ˆ
688
+
689
+ ์‹œ๊ฐ„๋Œ€๋ณ„ ๋‚ ์”จ ๋ฐ์ดํ„ฐ:
690
+ {forecast_data_str}"""}
691
+ ]
692
+ )
693
+
694
+ st.session_state.weather_forecast = response.choices[0].message.content
695
+
696
+ # ์ €์žฅ๋œ ๋‚ ์”จ ์˜ˆ๋ณด ํ‘œ์‹œ
697
+ st.markdown(f'''
698
+ <div class="scroll-container">
699
+ <div class="scroll-text">{st.session_state.weather_forecast}</div>
700
  </div>
701
+ ''', unsafe_allow_html=True)
 
 
702
 
703
  # ์Šคํฌ๋กค ํ…์ŠคํŠธ ์œ„์— ๋ฒ„ํŠผ์ด ์˜ค๋„๋ก ๋งˆ์ง„ ์ถ”๊ฐ€
704
  st.markdown('''
705
+ <div style="margin-bottom: 10px;">
 
 
 
 
706
  ''', unsafe_allow_html=True)
707
 
708
  # ์šฐ๋ฆฌ์ง‘ ๋‚ ์”จ ์ •๋ณด๋กœ ๋Œ์•„๊ฐ€๊ธฐ ๋ฒ„ํŠผ ์ถ”๊ฐ€
 
710
 
711
  st.markdown('</div>', unsafe_allow_html=True)
712
 
 
713
  def main():
714
  if 'current_section' not in st.session_state:
715
  st.session_state.current_section = 'weather'