openfree commited on
Commit
0d187fd
·
verified ·
1 Parent(s): 11566a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +158 -188
app.py CHANGED
@@ -11,51 +11,50 @@ from zoneinfo import ZoneInfo
11
  # OpenAI API 키를 환경변수에서 가져오기
12
  API_KEY = os.getenv("API_KEY")
13
 
14
- # 전세계 주요 도시 시간대 딕셔너리
15
- TIMEZONE_CITIES = {
16
- "서울 (UTC+9)": "Asia/Seoul",
17
- "도쿄 (UTC+9)": "Asia/Tokyo",
18
- "베이징 (UTC+8)": "Asia/Shanghai",
19
- "싱가포르 (UTC+8)": "Asia/Singapore",
20
- "방콕 (UTC+7)": "Asia/Bangkok",
21
- "뉴델리 (UTC+5:30)": "Asia/Kolkata",
22
- "두바이 (UTC+4)": "Asia/Dubai",
23
- "모스크바 (UTC+3)": "Europe/Moscow",
24
- "이스탄불 (UTC+3)": "Europe/Istanbul",
25
- "파리 (UTC+1)": "Europe/Paris",
26
- "런던 (UTC+0)": "Europe/London",
27
- "리스본 (UTC+0)": "Europe/Lisbon",
28
- "상파울루 (UTC-3)": "America/Sao_Paulo",
29
- "뉴욕 (UTC-5)": "America/New_York",
30
- "시카고 (UTC-6)": "America/Chicago",
31
- "덴버 (UTC-7)": "America/Denver",
32
- "로스앤젤레스 (UTC-8)": "America/Los_Angeles",
33
- "앵커리지 (UTC-9)": "America/Anchorage",
34
- "호놀룰루 (UTC-10)": "Pacific/Honolulu",
35
- "시드니 (UTC+11)": "Australia/Sydney",
36
- "오클랜드 (UTC+13)": "Pacific/Auckland"
 
 
 
 
 
37
  }
38
 
39
- def exception_handler(exception_type, exception, traceback):
40
- print(f"{exception_type.__name__}: {exception}")
41
-
42
- sys.excepthook = exception_handler
43
- sys.tracebacklimit = 0
44
-
45
- def convert_to_seoul_time(year, month, day, hour, minute, selected_timezone):
46
  """
47
  선택된 시간대의 시간을 서울 시간으로 변환
48
  """
49
- # 선택된 시간대 객체 생성
50
- local_tz = pytz.timezone(TIMEZONE_CITIES[selected_timezone])
51
- seoul_tz = pytz.timezone('Asia/Seoul')
52
 
53
- # 현지 시간 생성
54
- local_time = local_tz.localize(datetime(int(year), int(month), int(day),
55
- int(hour), int(minute)))
56
 
57
- # 서울 시간으로 변환
58
- seoul_time = local_time.astimezone(seoul_tz)
 
 
 
59
 
60
  return {
61
  'year': str(seoul_time.year),
@@ -64,6 +63,13 @@ def convert_to_seoul_time(year, month, day, hour, minute, selected_timezone):
64
  'hour': f"{seoul_time.hour:02d}{seoul_time.minute:02d}"
65
  }
66
 
 
 
 
 
 
 
 
67
  def get_chinese_hour(birth_hour):
68
  hour = int(birth_hour[:2])
69
  chinese_hours = ['자', '축', '인', '묘', '진', '사', '오', '미', '신', '유', '술', '해']
@@ -151,14 +157,16 @@ def calculate_siju(birth_hour, lunIljin):
151
 
152
  return siju
153
 
154
- def get_lunar_info(solYear, solMonth, solDay, solHour, selected_timezone):
 
155
  try:
156
  # 시간 파싱
157
  hour = int(solHour[:2])
158
  minute = int(solHour[2:]) if len(solHour) > 2 else 0
159
 
160
  # 선택된 시간대에서 서울 시간으로 변환
161
- seoul_time = convert_to_seoul_time(solYear, solMonth, solDay, hour, minute, selected_timezone)
 
162
 
163
  base_url = "http://apis.data.go.kr/B090041/openapi/service/LrsrCldInfoService/getLunCalInfo"
164
  service_key = "EuBjt%2B2t0KzYt5Ri%2Bzs56oymt9kHJ8uPIOV7m6UMKnOV8cpwj02EiRqMEudX%2F%2FVTKdMnwaLH0igRwY57YUplEQ%3D%3D"
@@ -350,6 +358,7 @@ button {
350
  button:hover {
351
  transform: translateY(-2px);
352
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
 
353
  }
354
 
355
  /* 입력 컨테이너 스타일 */
@@ -359,6 +368,12 @@ button:hover {
359
  padding: 20px;
360
  margin: 10px 0;
361
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
 
 
 
 
 
 
362
  }
363
 
364
  /* 출력 컨테이너 스타일 */
@@ -370,96 +385,86 @@ button:hover {
370
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
371
  }
372
 
373
- /* 시간대 선택 드롭다운 스타일 */
374
- .timezone-dropdown {
375
- background: white;
376
- border-radius: 8px;
377
- padding: 10px;
378
- margin: 10px 0;
379
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
380
- }
381
-
382
- /* 분석 결과 스타일 */
383
- .analysis-result {
384
- background: white;
385
  border-radius: 10px;
386
- padding: 20px;
387
- margin: 15px 0;
388
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
389
  }
390
 
 
 
 
 
 
391
 
392
- footer { visibility: hidden; }
393
-
394
- /* 전체 컨테이너 스타일 */
395
- .container {
396
- background: linear-gradient(135deg, #6e8efb, #a777e3);
397
- border-radius: 15px;
398
- box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
399
- backdrop-filter: blur(4px);
400
- border: 1px solid rgba(255, 255, 255, 0.18);
401
- padding: 20px;
402
- margin: 10px;
403
  }
404
 
405
- /* 버튼 스타일 */
406
- button {
407
- background: linear-gradient(135deg, #FF6B6B, #FF8E53);
408
- border: none;
409
- color: white;
410
- padding: 12px 24px;
411
- text-align: center;
412
- font-size: 16px;
413
- border-radius: 8px;
414
- cursor: pointer;
415
- transition: all 0.3s ease;
416
- font-weight: bold;
417
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
418
  }
419
 
420
- button:hover {
421
- transform: translateY(-2px);
422
- box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
 
 
 
423
  }
424
 
425
- /* 입력 컨테이너 스타일 */
426
- .input-container {
427
- background: rgba(255, 255, 255, 0.95);
428
- border-radius: 10px;
429
- padding: 20px;
430
- margin: 10px 0;
431
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
 
432
  }
433
 
434
- /* 출력 컨테이너 스타일 */
435
- .output-container {
436
- background: linear-gradient(135deg, #f6f9fc, #eef2f7);
437
- border-radius: 10px;
438
- padding: 20px;
439
- margin: 10px 0;
440
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
441
  }
442
 
443
  /* 큰 출력 박스 스타일 */
444
  .large-output-box {
445
  height: 500px !important;
446
  font-size: 16px !important;
447
- padding: 20px !important;
448
  background: linear-gradient(135deg, #f6f9fc, #eef2f7);
449
  border-radius: 15px;
450
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
451
  margin: 20px 0;
452
  overflow-y: auto;
453
- line-height: 1.6;
454
  white-space: pre-wrap;
 
 
 
 
 
 
455
  }
456
 
457
  /* 탭 내비게이션 스타일 */
458
  .tab-nav {
459
  background: rgba(255, 255, 255, 0.9);
460
- border-radius: 10px;
461
- padding: 10px;
462
- margin-bottom: 20px;
 
463
  }
464
 
465
  /* 마크다운 텍스트 스타일 */
@@ -467,34 +472,59 @@ button:hover {
467
  text-align: center;
468
  color: #2d3748;
469
  text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
 
 
470
  }
471
 
472
  /* 신년운세 특별 스타일 */
473
  .newyear-container {
474
  background: linear-gradient(135deg, #ffd1d1, #ffecd1);
475
- padding: 30px;
476
  border-radius: 20px;
477
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
478
- margin: 20px 0;
 
 
 
 
 
 
479
  }
480
 
481
  .newyear-title {
482
- font-size: 24px;
483
  color: #2d3748;
484
  text-align: center;
485
- margin-bottom: 20px;
486
  text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
 
487
  }
488
 
489
  /* 탭 컨텐츠 스타일 */
490
  .tab-content {
491
  min-height: 600px;
492
- padding: 20px;
 
 
 
493
  }
494
- """
495
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
 
497
- # Gradio 인터페이스
498
  with gr.Blocks(css=css) as demo:
499
  gr.Markdown("# 🔮 AI 사주 운세 분석 시스템 ✨", elem_id="title")
500
  gr.Markdown("### 🌟 양력 생년월일시와 출생 지역을 입력하시면 AI가 당신의 운세를 분석해드립니다! 💫", elem_id="description1")
@@ -509,12 +539,18 @@ with gr.Blocks(css=css) as demo:
509
  label="⏰ 생시 (예: 1030)",
510
  placeholder="24시간 형식으로 입력 (예: 2230)"
511
  )
512
- timezone_select = gr.Dropdown(
513
- choices=list(TIMEZONE_CITIES.keys()),
514
- value="서울 (UTC+9)",
515
- label="🌍 출생 지역 시간대",
516
- info="출생 지역의 시간대를 선택하세요. 모든 시간은 서울 시간으로 자동 변환됩니다.",
517
- elem_classes="timezone-dropdown"
 
 
 
 
 
 
518
  )
519
 
520
  with gr.Group(elem_classes="output-container"):
@@ -523,6 +559,10 @@ with gr.Blocks(css=css) as demo:
523
  lunIljin_state = gr.State()
524
 
525
  get_lunar_info_btn = gr.Button("✨ 운세 분석하기")
 
 
 
 
526
 
527
  with gr.Tab("🧐 성격과 특징 분석"):
528
  with gr.Group(elem_classes="output-container"):
@@ -547,13 +587,17 @@ with gr.Blocks(css=css) as demo:
547
  )
548
  analyze_button2 = gr.Button("🎯 2025년 운세 보기", size="large")
549
 
 
 
 
550
  # 이벤트 연결
551
  get_lunar_info_btn.click(
552
  fn=get_lunar_info,
553
- inputs=[solYear, solMonth, solDay, solHour, timezone_select],
554
  outputs=[output1, lunIljin_state, analysis_result]
555
  )
556
-
 
557
  analyze_button.click(
558
  fn=analyze_character,
559
  inputs=[lunIljin_state],
@@ -570,77 +614,3 @@ with gr.Blocks(css=css) as demo:
570
  demo.launch()
571
 
572
 
573
-
574
-
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
- # Gradio 인터페이스
584
- with gr.Blocks(css=css) as demo:
585
- gr.Markdown("# 🔮 AI 사주 운세 분석 시스템 ✨", elem_id="title")
586
- gr.Markdown("### 🌟 양력 생년월일시를 입력하시면 AI가 당신의 운세를 분석해드립니다! 💫", elem_id="description1")
587
- gr.Markdown("### 💫 커뮤니티: https://discord.gg/openfreeai 🌈", elem_id="description3")
588
-
589
- with gr.Tab("📝 기본 정보 입력 및 요약"):
590
- with gr.Group(elem_classes="input-container"):
591
- solYear = gr.Textbox(label="🎂 생년 (예: 1990)")
592
- solMonth = gr.Textbox(label="📅 생월 (예: 01)")
593
- solDay = gr.Textbox(label="📆 생일 (예: 31)")
594
- solHour = gr.Textbox(
595
- label="⏰ 생시 (예: 1030)",
596
- placeholder="24시간 형식으로 입력 (예: 2230)"
597
- )
598
-
599
- with gr.Group(elem_classes="output-container"):
600
- output1 = gr.JSON(label="🎯 사주 분석 결과")
601
- analysis_result = gr.HTML()
602
- lunIljin_state = gr.State()
603
-
604
- get_lunar_info_btn = gr.Button("✨ 운세 분석하기")
605
-
606
- with gr.Tab("🧐 성격과 특징 분석"):
607
- with gr.Group(elem_classes="output-container"):
608
- character_output = gr.Textbox(
609
- label="🎭 당신의 성격과 특징",
610
- elem_classes="large-output-box"
611
- )
612
- analyze_button = gr.Button("🔍 성격 분석하기")
613
-
614
- with gr.Tab("🎊 2025년 운세"):
615
- with gr.Group(elem_classes="newyear-container"):
616
- gr.Markdown("### 🌟 2025년 을사년 신년운세 🌟", elem_classes="newyear-title")
617
- newyear_output = gr.Textbox(
618
- label="🎉 상세 운세 분석",
619
- elem_classes="large-output-box",
620
- lines=20,
621
- max_lines=30,
622
- show_label=True,
623
- placeholder="운세 분석 결과가 여기에 표시됩니다..."
624
- )
625
- analyze_button2 = gr.Button("🎯 2025년 운세 보기", size="large")
626
-
627
- # 이벤트 연결
628
- get_lunar_info_btn.click(
629
- fn=get_lunar_info,
630
- inputs=[solYear, solMonth, solDay, solHour],
631
- outputs=[output1, lunIljin_state, analysis_result]
632
- )
633
-
634
- analyze_button.click(
635
- fn=analyze_character,
636
- inputs=[lunIljin_state],
637
- outputs=character_output
638
- )
639
-
640
- analyze_button2.click(
641
- fn=analyze_2024,
642
- inputs=[lunIljin_state],
643
- outputs=newyear_output
644
- )
645
-
646
- demo.launch()
 
11
  # OpenAI API 키를 환경변수에서 가져오기
12
  API_KEY = os.getenv("API_KEY")
13
 
14
+ TIMEZONE_MAPPING = {
15
+ -12: "태평양/베이커 섬 (UTC-12)",
16
+ -11: "태평양/미드웨이 (UTC-11)",
17
+ -10: "태평양/호놀룰루 (UTC-10)",
18
+ -9: "미국/앵커리지 (UTC-9)",
19
+ -8: "미국/로스앤젤레스 (UTC-8)",
20
+ -7: "미국/덴버 (UTC-7)",
21
+ -6: "미국/시카고 (UTC-6)",
22
+ -5: "미국/뉴욕 (UTC-5)",
23
+ -4: "캐나다/핼리팩스 (UTC-4)",
24
+ -3: "브라질/상파울루 (UTC-3)",
25
+ -2: "대서양/남조지아 (UTC-2)",
26
+ -1: "대서양/아조레스 (UTC-1)",
27
+ 0: "영국/런던 (UTC+0)",
28
+ 1: "유럽/파리 (UTC+1)",
29
+ 2: "유럽/아테네 (UTC+2)",
30
+ 3: "유럽/모스크바 (UTC+3)",
31
+ 4: "아시아/두바이 (UTC+4)",
32
+ 5: "아시아/카라치 (UTC+5)",
33
+ 6: "아시아/다카 (UTC+6)",
34
+ 7: "아시아/방콕 (UTC+7)",
35
+ 8: "아시아/싱가포르 (UTC+8)",
36
+ 9: "아시아/서울 (UTC+9)",
37
+ 10: "아시아/시드니 (UTC+10)",
38
+ 11: "태평양/누메아 (UTC+11)",
39
+ 12: "태평양/오클랜드 (UTC+12)",
40
+ 13: "태평양/통가 (UTC+13)",
41
+ 14: "태평양/키리티마티 (UTC+14)"
42
  }
43
 
44
+ def convert_to_seoul_time(year, month, day, hour, minute, timezone_offset):
 
 
 
 
 
 
45
  """
46
  선택된 시간대의 시간을 서울 시간으로 변환
47
  """
48
+ from datetime import datetime, timedelta
 
 
49
 
50
+ # 서울과의 시차 계산 (서울은 UTC+9)
51
+ time_difference = 9 - int(timezone_offset)
 
52
 
53
+ # 입력 시간 생성
54
+ local_time = datetime(int(year), int(month), int(day), int(hour), int(minute))
55
+
56
+ # 시차 적용
57
+ seoul_time = local_time + timedelta(hours=time_difference)
58
 
59
  return {
60
  'year': str(seoul_time.year),
 
63
  'hour': f"{seoul_time.hour:02d}{seoul_time.minute:02d}"
64
  }
65
 
66
+ def exception_handler(exception_type, exception, traceback):
67
+ print(f"{exception_type.__name__}: {exception}")
68
+
69
+ sys.excepthook = exception_handler
70
+ sys.tracebacklimit = 0
71
+
72
+
73
  def get_chinese_hour(birth_hour):
74
  hour = int(birth_hour[:2])
75
  chinese_hours = ['자', '축', '인', '묘', '진', '사', '오', '미', '신', '유', '술', '해']
 
157
 
158
  return siju
159
 
160
+ # get_lunar_info 함수 수정
161
+ def get_lunar_info(solYear, solMonth, solDay, solHour, timezone_offset):
162
  try:
163
  # 시간 파싱
164
  hour = int(solHour[:2])
165
  minute = int(solHour[2:]) if len(solHour) > 2 else 0
166
 
167
  # 선택된 시간대에서 서울 시간으로 변환
168
+ seoul_time = convert_to_seoul_time(solYear, solMonth, solDay, hour, minute, timezone_offset)
169
+
170
 
171
  base_url = "http://apis.data.go.kr/B090041/openapi/service/LrsrCldInfoService/getLunCalInfo"
172
  service_key = "EuBjt%2B2t0KzYt5Ri%2Bzs56oymt9kHJ8uPIOV7m6UMKnOV8cpwj02EiRqMEudX%2F%2FVTKdMnwaLH0igRwY57YUplEQ%3D%3D"
 
358
  button:hover {
359
  transform: translateY(-2px);
360
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
361
+ background: linear-gradient(135deg, #FF8E53, #FF6B6B);
362
  }
363
 
364
  /* 입력 컨테이너 스타일 */
 
368
  padding: 20px;
369
  margin: 10px 0;
370
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
371
+ transition: all 0.3s ease;
372
+ }
373
+
374
+ .input-container:hover {
375
+ transform: translateY(-2px);
376
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
377
  }
378
 
379
  /* 출력 컨테이너 스타일 */
 
385
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
386
  }
387
 
388
+ /* 시간대 슬라이더 스타일 */
389
+ .timezone-slider {
390
+ margin: 20px 0;
391
+ padding: 15px;
392
+ background: linear-gradient(135deg, #ffffff, #f8f9fa);
 
 
 
 
 
 
 
393
  border-radius: 10px;
 
 
394
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
395
  }
396
 
397
+ .timezone-slider .slider {
398
+ height: 10px !important;
399
+ background: linear-gradient(90deg, #6e8efb, #a777e3) !important;
400
+ border-radius: 5px !important;
401
+ }
402
 
403
+ .timezone-slider .thumb {
404
+ width: 20px !important;
405
+ height: 20px !important;
406
+ background: white !important;
407
+ border: 2px solid #6e8efb !important;
408
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2) !important;
 
 
 
 
 
409
  }
410
 
411
+ .timezone-slider .label {
412
+ font-size: 14px;
413
+ font-weight: 500;
414
+ color: #2d3748;
415
+ margin-bottom: 10px;
 
 
 
 
 
 
 
 
416
  }
417
 
418
+ #selected-timezone-display {
419
+ text-align: center;
420
+ font-size: 14px;
421
+ color: #4a5568;
422
+ margin-top: 5px;
423
+ font-weight: 500;
424
  }
425
 
426
+ /* 분석 결과 스타일 */
427
+ .analysis-result {
428
+ background: white;
429
+ border-radius: 15px;
430
+ padding: 25px;
431
+ margin: 20px 0;
432
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
433
+ transition: all 0.3s ease;
434
  }
435
 
436
+ .analysis-result:hover {
437
+ transform: translateY(-2px);
438
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
 
 
 
 
439
  }
440
 
441
  /* 큰 출력 박스 스타일 */
442
  .large-output-box {
443
  height: 500px !important;
444
  font-size: 16px !important;
445
+ padding: 25px !important;
446
  background: linear-gradient(135deg, #f6f9fc, #eef2f7);
447
  border-radius: 15px;
448
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
449
  margin: 20px 0;
450
  overflow-y: auto;
451
+ line-height: 1.8;
452
  white-space: pre-wrap;
453
+ transition: all 0.3s ease;
454
+ }
455
+
456
+ .large-output-box:hover {
457
+ transform: translateY(-2px);
458
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
459
  }
460
 
461
  /* 탭 내비게이션 스타일 */
462
  .tab-nav {
463
  background: rgba(255, 255, 255, 0.9);
464
+ border-radius: 15px;
465
+ padding: 15px;
466
+ margin-bottom: 25px;
467
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
468
  }
469
 
470
  /* 마크다운 텍스트 스타일 */
 
472
  text-align: center;
473
  color: #2d3748;
474
  text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
475
+ font-weight: 500;
476
+ margin: 20px 0;
477
  }
478
 
479
  /* 신년운세 특별 스타일 */
480
  .newyear-container {
481
  background: linear-gradient(135deg, #ffd1d1, #ffecd1);
482
+ padding: 35px;
483
  border-radius: 20px;
484
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
485
+ margin: 25px 0;
486
+ transition: all 0.3s ease;
487
+ }
488
+
489
+ .newyear-container:hover {
490
+ transform: translateY(-2px);
491
+ box-shadow: 0 15px 50px rgba(0, 0, 0, 0.15);
492
  }
493
 
494
  .newyear-title {
495
+ font-size: 26px;
496
  color: #2d3748;
497
  text-align: center;
498
+ margin-bottom: 25px;
499
  text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
500
+ font-weight: bold;
501
  }
502
 
503
  /* 탭 컨텐츠 스타일 */
504
  .tab-content {
505
  min-height: 600px;
506
+ padding: 25px;
507
+ background: rgba(255, 255, 255, 0.02);
508
+ border-radius: 15px;
509
+ backdrop-filter: blur(10px);
510
  }
 
511
 
512
+ /* 입력 필드 스타일 */
513
+ input, select, textarea {
514
+ border-radius: 8px !important;
515
+ border: 1px solid rgba(0, 0, 0, 0.1) !important;
516
+ padding: 12px !important;
517
+ transition: all 0.3s ease !important;
518
+ }
519
+
520
+ input:focus, select:focus, textarea:focus {
521
+ border-color: #6e8efb !important;
522
+ box-shadow: 0 0 0 2px rgba(110, 142, 251, 0.2) !important;
523
+ transform: translateY(-1px);
524
+ }
525
+ """
526
 
527
+ # Gradio UI 부분
528
  with gr.Blocks(css=css) as demo:
529
  gr.Markdown("# 🔮 AI 사주 운세 분석 시스템 ✨", elem_id="title")
530
  gr.Markdown("### 🌟 양력 생년월일시와 출생 지역을 입력하시면 AI가 당신의 운세를 분석해드립니다! 💫", elem_id="description1")
 
539
  label="⏰ 생시 (예: 1030)",
540
  placeholder="24시간 형식으로 입력 (예: 2230)"
541
  )
542
+ timezone_slider = gr.Slider(
543
+ minimum=-12,
544
+ maximum=14,
545
+ value=9,
546
+ step=1,
547
+ label="🌍 출생 지역 시간대 (UTC)",
548
+ info="서울은 UTC+9 입니다. 출생 지역의 UTC 시간대를 선택하세요.",
549
+ elem_classes="timezone-slider"
550
+ )
551
+ gr.Markdown(
552
+ "현재 선택된 시간대: " + TIMEZONE_MAPPING[9],
553
+ elem_id="selected-timezone-display"
554
  )
555
 
556
  with gr.Group(elem_classes="output-container"):
 
559
  lunIljin_state = gr.State()
560
 
561
  get_lunar_info_btn = gr.Button("✨ 운세 분석하기")
562
+
563
+
564
+
565
+
566
 
567
  with gr.Tab("🧐 성격과 특징 분석"):
568
  with gr.Group(elem_classes="output-container"):
 
587
  )
588
  analyze_button2 = gr.Button("🎯 2025년 운세 보기", size="large")
589
 
590
+
591
+
592
+
593
  # 이벤트 연결
594
  get_lunar_info_btn.click(
595
  fn=get_lunar_info,
596
+ inputs=[solYear, solMonth, solDay, solHour, timezone_slider],
597
  outputs=[output1, lunIljin_state, analysis_result]
598
  )
599
+
600
+
601
  analyze_button.click(
602
  fn=analyze_character,
603
  inputs=[lunIljin_state],
 
614
  demo.launch()
615
 
616