Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -0,0 +1,366 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import datetime
|
3 |
+
from datetime import datetime, timedelta
|
4 |
+
import requests
|
5 |
+
import json
|
6 |
+
|
7 |
+
class SajuCalculator:
|
8 |
+
def __init__(self):
|
9 |
+
# 천간 (하늘줄기)
|
10 |
+
self.heavenly_stems = ['갑', '을', '병', '정', '무', '기', '경', '신', '임', '계']
|
11 |
+
|
12 |
+
# 지지 (땅가지)
|
13 |
+
self.earthly_branches = ['자', '축', '인', '묘', '진', '사', '오', '미', '신', '유', '술', '해']
|
14 |
+
|
15 |
+
# 오행
|
16 |
+
self.five_elements = {
|
17 |
+
'갑': '목', '을': '목', '병': '화', '정': '화', '무': '토',
|
18 |
+
'기': '토', '경': '금', '신': '금', '임': '수', '계': '수',
|
19 |
+
'자': '수', '축': '토', '인': '목', '묘': '목', '진': '토',
|
20 |
+
'사': '화', '오': '화', '미': '토', '신': '금', '유': '금',
|
21 |
+
'술': '토', '해': '수'
|
22 |
+
}
|
23 |
+
|
24 |
+
# 십신
|
25 |
+
self.ten_gods = {
|
26 |
+
'목': {'목': '비견/겁재', '화': '식신/상관', '토': '편재/정재', '금': '편관/정관', '수': '편인/정인'},
|
27 |
+
'화': {'목': '편인/정인', '화': '비견/겁재', '토': '식신/상관', '금': '편재/정재', '수': '편관/정관'},
|
28 |
+
'토': {'목': '편관/정관', '화': '편인/정인', '토': '비견/겁재', '금': '식신/상관', '수': '편재/정재'},
|
29 |
+
'금': {'목': '편재/정재', '화': '편관/정관', '토': '편인/정인', '금': '비견/겁재', '수': '식신/상관'},
|
30 |
+
'수': {'목': '식신/상관', '화': '편재/정재', '토': '편관/정관', '금': '편인/정인', '수': '비견/겁재'}
|
31 |
+
}
|
32 |
+
|
33 |
+
# 색상 매핑
|
34 |
+
self.element_colors = {
|
35 |
+
'목': '#28a745', # 녹색
|
36 |
+
'화': '#dc3545', # 빨강
|
37 |
+
'토': '#ffc107', # 노랑
|
38 |
+
'금': '#6c757d', # 회색
|
39 |
+
'수': '#007bff' # 파랑
|
40 |
+
}
|
41 |
+
|
42 |
+
def get_ganzhi(self, year, month, day, hour):
|
43 |
+
"""간지 계산"""
|
44 |
+
# 기준일: 1900년 1월 1일 (경자년 정축월 갑인일)
|
45 |
+
base_date = datetime(1900, 1, 1)
|
46 |
+
target_date = datetime(year, month, day)
|
47 |
+
|
48 |
+
days_diff = (target_date - base_date).days
|
49 |
+
|
50 |
+
# 연주 계산
|
51 |
+
year_stem_index = (year - 1900 + 6) % 10 # 1900년이 경년(6)
|
52 |
+
year_branch_index = (year - 1900 + 0) % 12 # 1900년이 자년(0)
|
53 |
+
|
54 |
+
# 월주 계산 (절기 고려해야 하지만 간단히 처리)
|
55 |
+
month_stem_index = (year_stem_index * 2 + month + 1) % 10
|
56 |
+
month_branch_index = (month + 1) % 12
|
57 |
+
|
58 |
+
# 일주 계산
|
59 |
+
day_stem_index = (days_diff + 10) % 10 # 1900.1.1이 갑일
|
60 |
+
day_branch_index = (days_diff + 2) % 12 # 1900.1.1이 인일
|
61 |
+
|
62 |
+
# 시주 계산
|
63 |
+
hour_branch_index = ((hour + 1) // 2) % 12
|
64 |
+
hour_stem_index = (day_stem_index * 2 + hour_branch_index) % 10
|
65 |
+
|
66 |
+
return {
|
67 |
+
'year': (self.heavenly_stems[year_stem_index], self.earthly_branches[year_branch_index]),
|
68 |
+
'month': (self.heavenly_stems[month_stem_index], self.earthly_branches[month_branch_index]),
|
69 |
+
'day': (self.heavenly_stems[day_stem_index], self.earthly_branches[day_branch_index]),
|
70 |
+
'hour': (self.heavenly_stems[hour_stem_index], self.earthly_branches[hour_branch_index])
|
71 |
+
}
|
72 |
+
|
73 |
+
def analyze_elements(self, ganzhi):
|
74 |
+
"""오행 분석"""
|
75 |
+
elements = []
|
76 |
+
for pillar in ganzhi.values():
|
77 |
+
stem_element = self.five_elements[pillar[0]]
|
78 |
+
branch_element = self.five_elements[pillar[1]]
|
79 |
+
elements.extend([stem_element, branch_element])
|
80 |
+
|
81 |
+
element_count = {}
|
82 |
+
for element in ['목', '화', '토', '금', '수']:
|
83 |
+
element_count[element] = elements.count(element)
|
84 |
+
|
85 |
+
return element_count
|
86 |
+
|
87 |
+
def get_ten_gods_analysis(self, ganzhi):
|
88 |
+
"""십신 분석"""
|
89 |
+
day_stem = ganzhi['day'][0]
|
90 |
+
day_element = self.five_elements[day_stem]
|
91 |
+
|
92 |
+
analysis = {}
|
93 |
+
for pillar_name, pillar in ganzhi.items():
|
94 |
+
stem_element = self.five_elements[pillar[0]]
|
95 |
+
branch_element = self.five_elements[pillar[1]]
|
96 |
+
|
97 |
+
stem_relation = self.ten_gods[day_element][stem_element]
|
98 |
+
branch_relation = self.ten_gods[day_element][branch_element]
|
99 |
+
|
100 |
+
analysis[pillar_name] = {
|
101 |
+
'stem_relation': stem_relation,
|
102 |
+
'branch_relation': branch_relation
|
103 |
+
}
|
104 |
+
|
105 |
+
return analysis
|
106 |
+
|
107 |
+
def calculate_daeun(self, birth_year, gender):
|
108 |
+
"""대운 계산 (간단한 버전)"""
|
109 |
+
daeun_list = []
|
110 |
+
start_age = 8 if gender == '남' else 7 # 간단히 설정
|
111 |
+
|
112 |
+
for i in range(8): # 8개 대운
|
113 |
+
age_start = start_age + i * 10
|
114 |
+
age_end = age_start + 9
|
115 |
+
year_start = birth_year + age_start
|
116 |
+
year_end = birth_year + age_end
|
117 |
+
|
118 |
+
# 대운 간지는 월주를 기준으로 순행/역행
|
119 |
+
daeun_list.append({
|
120 |
+
'period': f"{age_start}-{age_end}세",
|
121 |
+
'years': f"{year_start}-{year_end}년",
|
122 |
+
'ganzhi': f"대운{i+1}" # 실제로는 복잡한 계산 필요
|
123 |
+
})
|
124 |
+
|
125 |
+
return daeun_list
|
126 |
+
|
127 |
+
def calculate_saju(birth_date, birth_time, gender, birth_place):
|
128 |
+
"""사주 계산 메인 함수"""
|
129 |
+
try:
|
130 |
+
# 날짜 파싱
|
131 |
+
birth_datetime = datetime.strptime(f"{birth_date} {birth_time}", "%Y-%m-%d %H:%M")
|
132 |
+
|
133 |
+
calculator = SajuCalculator()
|
134 |
+
|
135 |
+
# 간지 계산
|
136 |
+
ganzhi = calculator.get_ganzhi(
|
137 |
+
birth_datetime.year,
|
138 |
+
birth_datetime.month,
|
139 |
+
birth_datetime.day,
|
140 |
+
birth_datetime.hour
|
141 |
+
)
|
142 |
+
|
143 |
+
# 오행 분석
|
144 |
+
elements = calculator.analyze_elements(ganzhi)
|
145 |
+
|
146 |
+
# 십신 분석
|
147 |
+
ten_gods = calculator.get_ten_gods_analysis(ganzhi)
|
148 |
+
|
149 |
+
# 대운 계산
|
150 |
+
daeun = calculator.calculate_daeun(birth_datetime.year, gender)
|
151 |
+
|
152 |
+
# 결과 포맷팅
|
153 |
+
result = format_saju_result(ganzhi, elements, ten_gods, daeun, birth_datetime, gender, birth_place)
|
154 |
+
|
155 |
+
return result
|
156 |
+
|
157 |
+
except Exception as e:
|
158 |
+
return f"❌ 계산 중 오류가 발생했습니다: {str(e)}"
|
159 |
+
|
160 |
+
def format_saju_result(ganzhi, elements, ten_gods, daeun, birth_datetime, gender, birth_place):
|
161 |
+
"""사주 결과 포맷팅"""
|
162 |
+
|
163 |
+
result = f"""
|
164 |
+
# 🔮 사주명리 만세력 분석결과
|
165 |
+
|
166 |
+
## 📋 기본정보
|
167 |
+
- **생년월일**: {birth_datetime.strftime('%Y년 %m월 %d일')}
|
168 |
+
- **출생시간**: {birth_datetime.strftime('%H시 %M분')}
|
169 |
+
- **성별**: {gender}
|
170 |
+
- **출생지**: {birth_place}
|
171 |
+
|
172 |
+
## 🏛️ 사주(四柱) - 만세력
|
173 |
+
|
174 |
+
### 연주(年柱) - 뿌리, 조상
|
175 |
+
**{ganzhi['year'][0]}{ganzhi['year'][1]}**
|
176 |
+
- 천간: {ganzhi['year'][0]} ({calculator.five_elements[ganzhi['year'][0]]})
|
177 |
+
- 지지: {ganzhi['year'][1]} ({calculator.five_elements[ganzhi['year'][1]]})
|
178 |
+
|
179 |
+
### 월주(月柱) - 줄기, 부모
|
180 |
+
**{ganzhi['month'][0]}{ganzhi['month'][1]}**
|
181 |
+
- 천간: {ganzhi['month'][0]} ({calculator.five_elements[ganzhi['month'][0]]})
|
182 |
+
- 지지: {ganzhi['month'][1]} ({calculator.five_elements[ganzhi['month'][1]]})
|
183 |
+
|
184 |
+
### 일주(日柱) - 본인, 배우자
|
185 |
+
**{ganzhi['day'][0]}{ganzhi['day'][1]}** (일간: {ganzhi['day'][0]})
|
186 |
+
- 천간: {ganzhi['day'][0]} ({calculator.five_elements[ganzhi['day'][0]]})
|
187 |
+
- 지지: {ganzhi['day'][1]} ({calculator.five_elements[ganzhi['day'][1]]})
|
188 |
+
|
189 |
+
### 시주(時柱) - 꽃, 자식
|
190 |
+
**{ganzhi['hour'][0]}{ganzhi['hour'][1]}**
|
191 |
+
- 천간: {ganzhi['hour'][0]} ({calculator.five_elements[ganzhi['hour'][0]]})
|
192 |
+
- 지지: {ganzhi['hour'][1]} ({calculator.five_elements[ganzhi['hour'][1]]})
|
193 |
+
|
194 |
+
## 🌟 오행(五行) 분석
|
195 |
+
|
196 |
+
"""
|
197 |
+
|
198 |
+
calculator = SajuCalculator()
|
199 |
+
|
200 |
+
# 오행 분석 추가
|
201 |
+
total_elements = sum(elements.values())
|
202 |
+
for element, count in elements.items():
|
203 |
+
percentage = (count / total_elements * 100) if total_elements > 0 else 0
|
204 |
+
result += f"- **{element}**: {count}개 ({percentage:.1f}%)\n"
|
205 |
+
|
206 |
+
# 오행 균형 분석
|
207 |
+
max_element = max(elements, key=elements.get)
|
208 |
+
min_element = min(elements, key=elements.get)
|
209 |
+
|
210 |
+
result += f"""
|
211 |
+
### 오행 균형 분석
|
212 |
+
- **가장 강한 오행**: {max_element} ({elements[max_element]}개)
|
213 |
+
- **가장 약한 오행**: {min_element} ({elements[min_element]}개)
|
214 |
+
"""
|
215 |
+
|
216 |
+
# 십신 분석 추가
|
217 |
+
result += """
|
218 |
+
## 🎭 십신(十神) 분석
|
219 |
+
|
220 |
+
"""
|
221 |
+
|
222 |
+
pillar_names = {'year': '연주', 'month': '월주', 'day': '일주', 'hour': '시주'}
|
223 |
+
for pillar_name, pillar_kr in pillar_names.items():
|
224 |
+
result += f"### {pillar_kr}\n"
|
225 |
+
result += f"- 천간: {ten_gods[pillar_name]['stem_relation']}\n"
|
226 |
+
result += f"- 지지: {ten_gods[pillar_name]['branch_relation']}\n\n"
|
227 |
+
|
228 |
+
# 대운 정보 추가
|
229 |
+
result += """
|
230 |
+
## 🔄 대운(大運) 정보
|
231 |
+
|
232 |
+
"""
|
233 |
+
|
234 |
+
for i, du in enumerate(daeun[:4]): # 처음 4개 대운만 표시
|
235 |
+
result += f"**{du['period']}** ({du['years']})\n"
|
236 |
+
|
237 |
+
# 기본 해석 추가
|
238 |
+
result += f"""
|
239 |
+
|
240 |
+
## 💡 기본 해석
|
241 |
+
|
242 |
+
### 성격 특성
|
243 |
+
- **일간**: {ganzhi['day'][0]} ({calculator.five_elements[ganzhi['day'][0]]})
|
244 |
+
- 일간이 {calculator.five_elements[ganzhi['day'][0]]}이므로, {get_element_personality(calculator.five_elements[ganzhi['day'][0]])}
|
245 |
+
|
246 |
+
### 오행 조화
|
247 |
+
{get_element_balance_advice(elements)}
|
248 |
+
|
249 |
+
### 주의사항
|
250 |
+
- 이 분석은 기본적인 사주명리학 원리에 따른 것입니다.
|
251 |
+
- 정확한 해석을 위해서는 전문가의 상담을 받으시기 바랍니다.
|
252 |
+
- 절기, 시간대, 지역별 차이 등이 고려되지 않았을 수 있습니다.
|
253 |
+
|
254 |
+
---
|
255 |
+
*생성일시: {datetime.now().strftime('%Y년 %m월 %d일 %H시 %M분')}*
|
256 |
+
"""
|
257 |
+
|
258 |
+
return result
|
259 |
+
|
260 |
+
def get_element_personality(element):
|
261 |
+
"""오행별 성격 특성"""
|
262 |
+
personalities = {
|
263 |
+
'목': "창의적이고 성장 지향적이며, 유연하고 협력적인 성격을 가지고 있습니다.",
|
264 |
+
'화': "열정적이고 활동적이며, 밝고 사교적인 성격을 가지고 있습니다.",
|
265 |
+
'토': "안정적이고 신중하며, 포용력이 있고 책임감이 강한 성격을 가지고 있습니다.",
|
266 |
+
'금': "원칙적이고 정의로우며, 결단력이 있고 리더십이 강한 성격을 가지고 있습니다.",
|
267 |
+
'수': "지혜롭고 적응력이 있으며, 깊이 있고 신중한 성격을 가지고 있습니다."
|
268 |
+
}
|
269 |
+
return personalities.get(element, "균형 잡힌 성격을 가지고 있습니다.")
|
270 |
+
|
271 |
+
def get_element_balance_advice(elements):
|
272 |
+
"""오행 균형에 따른 조언"""
|
273 |
+
max_element = max(elements, key=elements.get)
|
274 |
+
min_element = min(elements, key=elements.get)
|
275 |
+
|
276 |
+
advice = f"현재 {max_element}가 가장 강하고 {min_element}가 가장 약합니다. "
|
277 |
+
|
278 |
+
if elements[max_element] - elements[min_element] > 2:
|
279 |
+
advice += f"{min_element}를 보강하고 {max_element}의 기운을 조절하는 것이 좋겠습니다."
|
280 |
+
else:
|
281 |
+
advice += "전체적으로 균형이 잘 잡혀 있는 편입니다."
|
282 |
+
|
283 |
+
return advice
|
284 |
+
|
285 |
+
# Gradio 인터페이스 생성
|
286 |
+
def create_interface():
|
287 |
+
with gr.Blocks(title="🔮 사주명리 만세력 시스템", theme=gr.themes.Soft()) as demo:
|
288 |
+
gr.HTML("""
|
289 |
+
<div style="text-align: center; padding: 20px;">
|
290 |
+
<h1>🔮 사주명리학 만세력 분석 시스템</h1>
|
291 |
+
<p>생년월일시와 출생지 정보를 입력하시면 상세한 만세력을 분석해드립니다.</p>
|
292 |
+
</div>
|
293 |
+
""")
|
294 |
+
|
295 |
+
with gr.Row():
|
296 |
+
with gr.Column(scale=1):
|
297 |
+
gr.HTML("<h3>📝 정보 입력</h3>")
|
298 |
+
|
299 |
+
birth_date = gr.Date(
|
300 |
+
label="생년월일",
|
301 |
+
info="양력 기준으로 입력해주세요"
|
302 |
+
)
|
303 |
+
|
304 |
+
birth_time = gr.Textbox(
|
305 |
+
label="태어난 시간",
|
306 |
+
placeholder="14:30",
|
307 |
+
info="24시간 형식 (예: 14:30)"
|
308 |
+
)
|
309 |
+
|
310 |
+
gender = gr.Radio(
|
311 |
+
choices=["남", "여"],
|
312 |
+
label="성별",
|
313 |
+
value="남"
|
314 |
+
)
|
315 |
+
|
316 |
+
birth_place = gr.Textbox(
|
317 |
+
label="출생지",
|
318 |
+
placeholder="서울특별시",
|
319 |
+
info="시/도 단위로 입력해주세요"
|
320 |
+
)
|
321 |
+
|
322 |
+
calculate_btn = gr.Button(
|
323 |
+
"🔮 만세력 분석하기",
|
324 |
+
variant="primary",
|
325 |
+
size="lg"
|
326 |
+
)
|
327 |
+
|
328 |
+
with gr.Row():
|
329 |
+
with gr.Column():
|
330 |
+
result_output = gr.Markdown(
|
331 |
+
label="분석 결과",
|
332 |
+
elem_classes=["saju-result"]
|
333 |
+
)
|
334 |
+
|
335 |
+
# 이벤트 연결
|
336 |
+
calculate_btn.click(
|
337 |
+
fn=calculate_saju,
|
338 |
+
inputs=[birth_date, birth_time, gender, birth_place],
|
339 |
+
outputs=result_output
|
340 |
+
)
|
341 |
+
|
342 |
+
# 예시 데이터로 자동 실행
|
343 |
+
demo.load(
|
344 |
+
fn=lambda: calculate_saju("1990-05-15", "14:30", "남", "서울특별시"),
|
345 |
+
outputs=result_output
|
346 |
+
)
|
347 |
+
|
348 |
+
gr.HTML("""
|
349 |
+
<div style="text-align: center; padding: 20px; margin-top: 30px; border-top: 1px solid #eee;">
|
350 |
+
<p><small>※ 본 시스템은 전통 사주명리학을 기반으로 하며, 참고용으로만 활용해주시기 바랍니다.</small></p>
|
351 |
+
<p><small>※ 정확한 해석을 위해서는 전문가의 상담을 받으시기 바랍니다.</small></p>
|
352 |
+
</div>
|
353 |
+
""")
|
354 |
+
|
355 |
+
return demo
|
356 |
+
|
357 |
+
# 전역 변수로 계산기 인스턴스 생성
|
358 |
+
calculator = SajuCalculator()
|
359 |
+
|
360 |
+
if __name__ == "__main__":
|
361 |
+
demo = create_interface()
|
362 |
+
demo.launch(
|
363 |
+
server_name="0.0.0.0",
|
364 |
+
server_port=7860,
|
365 |
+
share=True
|
366 |
+
)
|