aliceblue11 commited on
Commit
d03c469
·
verified ·
1 Parent(s): ab0ab44

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +305 -1
app.py CHANGED
@@ -477,4 +477,308 @@ def create_saju_table(saju_data: Dict) -> str:
477
  <thead>
478
  <tr style='background: linear-gradient(135deg, #74b9ff, #0984e3); color: white;'>
479
  <th style='padding: 15px; border: 1px solid #ddd; font-size: 16px;'>년주 (祖上)</th>
480
- <th style='padding: 15px; border: 1px solid #ddd; font-size: 16px;'>월주 (父母)</th>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  <thead>
478
  <tr style='background: linear-gradient(135deg, #74b9ff, #0984e3); color: white;'>
479
  <th style='padding: 15px; border: 1px solid #ddd; font-size: 16px;'>년주 (祖上)</th>
480
+ <th style='padding: 15px; border: 1px solid #ddd; font-size: 16px;'>월주 (父母)</th>
481
+ <th style='padding: 15px; border: 1px solid #ddd; font-size: 16px;'>일주 (本人)</th>
482
+ <th style='padding: 15px; border: 1px solid #ddd; font-size: 16px;'>시주 (子女)</th>
483
+ </tr>
484
+ </thead>
485
+ <tbody>
486
+ <tr style='text-align: center; font-size: 20px; font-weight: bold;'>
487
+ <td style='padding: 20px; border: 1px solid #ddd; background: linear-gradient(135deg, #ffb3ba, #ff7675);'>{saju['year']}</td>
488
+ <td style='padding: 20px; border: 1px solid #ddd; background: linear-gradient(135deg, #bae1ff, #74b9ff);'>{saju['month']}</td>
489
+ <td style='padding: 20px; border: 1px solid #ddd; background: linear-gradient(135deg, #ffffba, #fdcb6e); border: 3px solid #f39c12;'>{saju['day']}</td>
490
+ <td style='padding: 20px; border: 1px solid #ddd; background: linear-gradient(135deg, #baffc9, #00b894);'>{saju['time']}</td>
491
+ </tr>
492
+ </tbody>
493
+ </table>
494
+ <p style='text-align: center; color: #7f8c8d; margin-bottom: 0;'>
495
+ <strong>일간:</strong> {detailed['day_master']} ({detailed['day_master_element']}) |
496
+ <strong>계절:</strong> {detailed['month_season']} |
497
+ <strong>강약:</strong> {detailed['strength']}
498
+ </p>
499
+ </div>
500
+
501
+ <div style='background: linear-gradient(135deg, #a29bfe 0%, #6c5ce7 100%); color: white; padding: 20px; border-radius: 12px; margin-bottom: 25px;'>
502
+ <h3 style='margin-top: 0; text-align: center;'>🌟 오행 분석</h3>
503
+ <div style='display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 15px; margin-bottom: 15px;'>"""
504
+
505
+ for element, count in elements['count'].items():
506
+ percentage = elements['percentage'].get(element, 0)
507
+ color_map = {'목': '#00b894', '화': '#e17055', '토': '#fdcb6e', '금': '#74b9ff', '수': '#6c5ce7'}
508
+ color = color_map.get(element, '#ddd')
509
+
510
+ table_html += f"""
511
+ <div style='background-color: rgba(255,255,255,0.2); padding: 12px; border-radius: 8px; text-align: center; backdrop-filter: blur(10px);'>
512
+ <div style='color: {color}; font-size: 18px; font-weight: bold;'>{element}</div>
513
+ <div style='font-size: 16px; margin: 5px 0;'>{count}개</div>
514
+ <div style='font-size: 12px;'>{percentage}%</div>
515
+ </div>"""
516
+
517
+ table_html += f"""
518
+ </div>
519
+ <div style='text-align: center; background-color: rgba(255,255,255,0.1); padding: 15px; border-radius: 8px;'>
520
+ <p style='margin: 5px 0;'><strong>🔥 우세 오행:</strong> {elements['dominant']}</p>
521
+ <p style='margin: 5px 0;'><strong>💧 부족 오행:</strong> {elements.get('weak', '균형적')}</p>
522
+ </div>
523
+ </div>
524
+
525
+ <div style='background-color: #fff; padding: 20px; border-radius: 12px; border: 2px solid #e74c3c; box-shadow: 0 4px 15px rgba(231,76,60,0.1);'>
526
+ <h3 style='color: #e74c3c; text-align: center; margin-bottom: 15px;'>⚡ 사주 구조 분석</h3>
527
+ <div style='display: grid; grid-template-columns: 1fr 1fr; gap: 20px;'>
528
+ <div style='background-color: #ffeaa7; padding: 15px; border-radius: 8px;'>
529
+ <h4 style='color: #2d3436; margin-top: 0;'>🎭 십성 구조</h4>
530
+ <p style='margin: 5px 0; color: #636e72;'>비견: {detailed['sipseong']['비견']}개</p>
531
+ <p style='margin: 5px 0; color: #636e72;'>식신: {detailed['sipseong']['식신']}개</p>
532
+ <p style='margin: 5px 0; color: #636e72;'>재성: {detailed['sipseong']['편재'] + detailed['sipseong']['정재']}개</p>
533
+ </div>
534
+ <div style='background-color: #81ecec; padding: 15px; border-radius: 8px;'>
535
+ <h4 style='color: #2d3436; margin-top: 0;'>🌊 오행 균형도</h4>
536
+ <p style='margin: 5px 0; color: #636e72;'>목: {elements['percentage'].get('목', 0)}%</p>
537
+ <p style='margin: 5px 0; color: #636e72;'>화: {elements['percentage'].get('화', 0)}%</p>
538
+ <p style='margin: 5px 0; color: #636e72;'>토: {elements['percentage'].get('토', 0)}%</p>
539
+ <p style='margin: 5px 0; color: #636e72;'>금: {elements['percentage'].get('금', 0)}%</p>
540
+ <p style='margin: 5px 0; color: #636e72;'>수: {elements['percentage'].get('수', 0)}%</p>
541
+ </div>
542
+ </div>
543
+ </div>
544
+ </div>
545
+ """
546
+
547
+ return table_html
548
+
549
+ def process_saju(name: str, birth_year: int, birth_month: int, birth_day: int,
550
+ birth_hour: int, birth_minute: int, gender: str, location: str,
551
+ calendar_type: str, is_intercalation: bool = False) -> Tuple[str, str]:
552
+ """사주 처리 메인 함수"""
553
+ try:
554
+ if not name.strip():
555
+ return "이름을 입력해주세요.", ""
556
+
557
+ if birth_year < 1000 or birth_year > 2050:
558
+ return "지원하는 연도 범위는 1000년~2050년입니다.", ""
559
+
560
+ if not (1 <= birth_month <= 12):
561
+ return "올바른 월을 입력해주세요 (1-12).", ""
562
+
563
+ if not (1 <= birth_day <= 31):
564
+ return "올바른 일을 입력해주세요 (1-31).", ""
565
+
566
+ if not (0 <= birth_hour <= 23):
567
+ return "올바른 시간을 입력해주세요 (0-23).", ""
568
+
569
+ calculator = SajuCalculator()
570
+ is_lunar = (calendar_type == "음력")
571
+
572
+ saju_data = calculator.calculate_saju(
573
+ name, birth_year, birth_month, birth_day,
574
+ birth_hour, birth_minute, gender, location, is_lunar, is_intercalation
575
+ )
576
+
577
+ # 사주 표 생성
578
+ saju_table = create_saju_table(saju_data)
579
+
580
+ # AI 해석 생성
581
+ ai_interpretation = get_ai_interpretation(saju_data)
582
+
583
+ return saju_table, ai_interpretation
584
+
585
+ except Exception as e:
586
+ error_msg = f"❌ 오류가 발생했습니다: {str(e)}"
587
+ return error_msg, error_msg
588
+
589
+ # Gradio 인터페이스 생성
590
+ def create_interface():
591
+ with gr.Blocks(
592
+ title="🔮 한국 전통 사주명리학 시스템",
593
+ theme=gr.themes.Soft(),
594
+ css="""
595
+ .gradio-container {
596
+ font-family: "Noto Sans KR", Arial, sans-serif !important;
597
+ }
598
+ .main-header {
599
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
600
+ color: white;
601
+ padding: 30px;
602
+ border-radius: 15px;
603
+ text-align: center;
604
+ margin-bottom: 30px;
605
+ }
606
+ """
607
+ ) as interface:
608
+
609
+ gr.HTML("""
610
+ <div class="main-header">
611
+ <h1 style="margin: 0; font-size: 2.5em;">🔮 한국 전통 사주명리학 시스템</h1>
612
+ <p style="margin: 10px 0 0 0; font-size: 1.2em; opacity: 0.9;">
613
+ 한국천문연구원 기준 정밀 음양력 변환 | AI 기반 전문가 해석
614
+ </p>
615
+ </div>
616
+ """)
617
+
618
+ with gr.Row():
619
+ with gr.Column(scale=1):
620
+ with gr.Group():
621
+ gr.Markdown("### 📝 개인정보")
622
+ name = gr.Textbox(
623
+ label="이름",
624
+ placeholder="홍길동",
625
+ info="정확한 이름을 입력해주세요"
626
+ )
627
+
628
+ with gr.Row():
629
+ gender = gr.Radio(
630
+ choices=["남자", "여자"],
631
+ label="성별",
632
+ value="남자"
633
+ )
634
+ location = gr.Textbox(
635
+ label="출생지",
636
+ placeholder="서울특별시",
637
+ info="태어난 도시를 입력해주세요"
638
+ )
639
+
640
+ with gr.Group():
641
+ gr.Markdown("### 📅 생년월일시")
642
+ calendar_type = gr.Radio(
643
+ choices=["양력", "음력"],
644
+ label="달력 구분",
645
+ value="양력",
646
+ info="양력/음력을 선택해주세요"
647
+ )
648
+
649
+ with gr.Row():
650
+ birth_year = gr.Number(
651
+ label="년도",
652
+ value=1990,
653
+ precision=0,
654
+ info="1000-2050년 지원"
655
+ )
656
+ birth_month = gr.Number(
657
+ label="월",
658
+ value=1,
659
+ precision=0,
660
+ minimum=1,
661
+ maximum=12
662
+ )
663
+ birth_day = gr.Number(
664
+ label="일",
665
+ value=1,
666
+ precision=0,
667
+ minimum=1,
668
+ maximum=31
669
+ )
670
+
671
+ with gr.Row():
672
+ birth_hour = gr.Number(
673
+ label="시 (24시간제)",
674
+ value=0,
675
+ precision=0,
676
+ minimum=0,
677
+ maximum=23,
678
+ info="정확한 출생시간이 중요합니다"
679
+ )
680
+ birth_minute = gr.Number(
681
+ label="분",
682
+ value=0,
683
+ precision=0,
684
+ minimum=0,
685
+ maximum=59
686
+ )
687
+
688
+ is_intercalation = gr.Checkbox(
689
+ label="윤달 여부 (음력인 경우만)",
690
+ value=False,
691
+ info="음력인 경우 윤달인지 확인해주세요",
692
+ visible=False
693
+ )
694
+
695
+ submit_btn = gr.Button(
696
+ "🔮 정밀 사주 분석 시작",
697
+ variant="primary",
698
+ size="lg",
699
+ elem_classes="submit-button"
700
+ )
701
+
702
+ gr.Markdown("""
703
+ ---
704
+ ### 💡 사용 팁
705
+ - **정확한 출생시간**: 2시간 차이로 시주가 바뀝니다
706
+ - **음력 주의**: 윤달 여부를 정확히 확인해주세요
707
+ - **절기 기준**: 명리학은 24절기로 월을 구분합니다
708
+ """)
709
+
710
+ with gr.Column(scale=2):
711
+ with gr.Tab("📊 사주명식"):
712
+ saju_output = gr.HTML(
713
+ label="사주 분석 결과",
714
+ elem_classes="saju-result"
715
+ )
716
+
717
+ with gr.Tab("🎯 AI 전문가 해석"):
718
+ interpretation_output = gr.Textbox(
719
+ label="상세 운세 해석",
720
+ lines=25,
721
+ placeholder="사주 해석 결과가 여기에 표시됩니다...",
722
+ show_copy_button=True,
723
+ elem_classes="interpretation-result"
724
+ )
725
+
726
+ # 이벤트 처리
727
+ def toggle_intercalation(calendar_type):
728
+ return gr.update(visible=(calendar_type == "음력"))
729
+
730
+ calendar_type.change(
731
+ fn=toggle_intercalation,
732
+ inputs=[calendar_type],
733
+ outputs=[is_intercalation]
734
+ )
735
+
736
+ submit_btn.click(
737
+ fn=process_saju,
738
+ inputs=[name, birth_year, birth_month, birth_day, birth_hour,
739
+ birth_minute, gender, location, calendar_type, is_intercalation],
740
+ outputs=[saju_output, interpretation_output]
741
+ )
742
+
743
+ gr.HTML("""
744
+ <div style="background-color: #f8f9fa; padding: 20px; border-radius: 10px; margin-top: 30px;">
745
+ <h3 style="color: #495057; text-align: center;">📌 시스템 특징</h3>
746
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 20px;">
747
+ <div style="text-align: center; padding: 15px;">
748
+ <div style="font-size: 24px; margin-bottom: 10px;">🎯</div>
749
+ <strong>한국천문연구원 기준</strong><br>
750
+ <small>정확한 음양력 변환</small>
751
+ </div>
752
+ <div style="text-align: center; padding: 15px;">
753
+ <div style="font-size: 24px; margin-bottom: 10px;">🤖</div>
754
+ <strong>AI 전문가 해석</strong><br>
755
+ <small>GPT-4 기반 상세 분석</small>
756
+ </div>
757
+ <div style="text-align: center; padding: 15px;">
758
+ <div style="font-size: 24px; margin-bottom: 10px;">🌿</div>
759
+ <strong>24절기 정확 반영</strong><br>
760
+ <small>전통 명리학 방식</small>
761
+ </div>
762
+ <div style="text-align: center; padding: 15px;">
763
+ <div style="font-size: 24px; margin-bottom: 10px;">📊</div>
764
+ <strong>상세 오행 분석</strong><br>
765
+ <small>십성과 강약 판단</small>
766
+ </div>
767
+ </div>
768
+ <p style="text-align: center; margin-top: 20px; color: #6c757d; font-style: italic;">
769
+ 💡 사주는 참고용으로만 활용하시고, 중요한 결정은 신중히 하시기 바랍니다.
770
+ </p>
771
+ </div>
772
+ """)
773
+
774
+ return interface
775
+
776
+ # 메인 실행
777
+ if __name__ == "__main__":
778
+ interface = create_interface()
779
+ interface.launch(
780
+ server_name="0.0.0.0",
781
+ server_port=7860,
782
+ share=True,
783
+ show_error=True
784
+ )