사주 풀이 고도화, NAS 배포 자동화
This commit is contained in:
@@ -2,6 +2,7 @@ import Link from 'next/link';
|
||||
import { calculateSaju, FIVE_ELEMENTS } from '@/lib/saju-calculator';
|
||||
import PDFButton from '../../components/PDFButton';
|
||||
import ShareButtons from '../../components/ShareButtons';
|
||||
import CompatibilityDetailUnlock from './CompatibilityDetailUnlock';
|
||||
|
||||
interface PageProps {
|
||||
searchParams: Promise<{
|
||||
@@ -18,102 +19,325 @@ interface PageProps {
|
||||
}>;
|
||||
}
|
||||
|
||||
// 오행 한글 매핑
|
||||
const elementKrMap: Record<string, string> = {
|
||||
'木': '목', '火': '화', '土': '토', '金': '금', '水': '수'
|
||||
};
|
||||
|
||||
// Deterministic hash for seeded score variation
|
||||
function seededOffset(seed: string, index: number): number {
|
||||
let hash = 0;
|
||||
const str = seed + index.toString();
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = ((hash << 5) - hash) + str.charCodeAt(i);
|
||||
hash |= 0;
|
||||
}
|
||||
return ((hash % 11) - 5); // -5 ~ +5
|
||||
}
|
||||
|
||||
// 오행 관계 타입 판별
|
||||
type ElementRelation = 'same' | 'produce' | 'produced' | 'overcome' | 'overcomed';
|
||||
|
||||
function getElementRelation(el1: string, el2: string): ElementRelation {
|
||||
const produceMap: Record<string, string> = {
|
||||
'木': '火', '火': '土', '土': '金', '金': '水', '水': '木'
|
||||
};
|
||||
if (el1 === el2) return 'same';
|
||||
if (produceMap[el1] === el2) return 'produce';
|
||||
if (produceMap[el2] === el1) return 'produced';
|
||||
const overcomeMap: Record<string, string> = {
|
||||
'木': '土', '火': '金', '土': '水', '金': '木', '水': '火'
|
||||
};
|
||||
if (overcomeMap[el1] === el2) return 'overcome';
|
||||
return 'overcomed';
|
||||
}
|
||||
|
||||
// 지지 관계 판별
|
||||
function getBranchRelation(b1: string, b2: string): { sixHarmony: boolean; threeHarmony: boolean; conflict: boolean } {
|
||||
const sixHarmony: Record<string, string> = {
|
||||
'子': '丑', '丑': '子', '寅': '亥', '亥': '寅',
|
||||
'卯': '戌', '戌': '卯', '辰': '酉', '酉': '辰',
|
||||
'巳': '申', '申': '巳', '午': '未', '未': '午'
|
||||
};
|
||||
const threeHarmonyGroups = [
|
||||
['申', '子', '辰'], ['寅', '午', '戌'],
|
||||
['亥', '卯', '未'], ['巳', '酉', '丑']
|
||||
];
|
||||
const conflictMap: Record<string, string> = {
|
||||
'子': '午', '午': '子', '丑': '未', '未': '丑',
|
||||
'寅': '申', '申': '寅', '卯': '酉', '酉': '卯',
|
||||
'辰': '戌', '戌': '辰', '巳': '亥', '亥': '巳'
|
||||
};
|
||||
|
||||
const isThreeHarmony = threeHarmonyGroups.some(g => g.includes(b1) && g.includes(b2));
|
||||
return {
|
||||
sixHarmony: sixHarmony[b1] === b2,
|
||||
threeHarmony: isThreeHarmony,
|
||||
conflict: conflictMap[b1] === b2,
|
||||
};
|
||||
}
|
||||
|
||||
// 오행 관계별 상세 해석
|
||||
function getElementInterpretation(el1: string, el2: string, relation: ElementRelation) {
|
||||
const el1Kr = elementKrMap[el1];
|
||||
const el2Kr = elementKrMap[el2];
|
||||
|
||||
const interpretations: Record<string, { pros: string[]; cons: string[]; advice: string }> = {
|
||||
// 상생: el1이 el2를 생함
|
||||
'木_火': {
|
||||
pros: [
|
||||
`${el1Kr}(나무)이 ${el2Kr}(불)을 키워주는 관계예요. 한 분이 자연스럽게 상대방에게 에너지를 전해주거든요.`,
|
||||
'성장을 응원하고 지지해주는 따뜻한 관계가 될 수 있어요.',
|
||||
'서로의 열정을 자극해서 함께 발전해 나갈 수 있는 좋은 조합이에요.',
|
||||
'함께 있으면 자연스럽게 활력이 넘치고, 창의적인 아이디어가 샘솟을 거예요.',
|
||||
],
|
||||
cons: [
|
||||
'한쪽이 너무 많이 희생하면 에너지가 소진될 수 있어요. 균형이 중요해요.',
|
||||
'불꽃처럼 열정적인 만큼 감정 기복이 클 수 있으니 차분한 대화가 필요해요.',
|
||||
'서로에 대한 기대가 커질 수 있어서, 적절한 거리감을 유지하는 것도 좋아요.',
|
||||
],
|
||||
advice: '서로의 에너지를 아낌없이 주되, 자기 자신도 잘 챙기는 게 이 관계의 핵심이에요.',
|
||||
},
|
||||
'火_土': {
|
||||
pros: [
|
||||
`${el1Kr}(불)이 ${el2Kr}(흙)을 따뜻하게 만들어주는 관계예요. 서로에게 안정감을 줄 수 있거든요.`,
|
||||
'열정과 안정이 조화를 이루어 실질적인 성과를 만들어낼 수 있어요.',
|
||||
'서로 다른 강점을 가지고 있어서 팀워크가 좋은 편이에요.',
|
||||
'어려운 순간에도 든든하게 의지할 수 있는 관계가 될 거예요.',
|
||||
],
|
||||
cons: [
|
||||
'급한 성격과 느긋한 성격이 부딪힐 수 있어요. 템포를 맞추는 연습이 필요해요.',
|
||||
'때로는 답답함을 느낄 수 있지만, 그만큼 서로를 보완해주는 관계이기도 해요.',
|
||||
'가끔은 서로의 속도 차이를 인정하고 기다려주는 여유가 필요하답니다.',
|
||||
],
|
||||
advice: '서로의 리듬을 존중하면서 함께 걸어가면, 오래오래 행복한 관계가 될 거예요.',
|
||||
},
|
||||
'土_金': {
|
||||
pros: [
|
||||
`${el1Kr}(흙)이 ${el2Kr}(쇠)를 품고 있는 관계예요. 안정 속에서 가치를 만들어내는 조합이에요.`,
|
||||
'현실적이고 실용적인 면에서 잘 맞아서 함께 무언가를 이뤄내기 좋아요.',
|
||||
'서로를 단단하게 만들어주는 든든한 파트너가 될 수 있어요.',
|
||||
'물질적으로나 정서적으로 안정감 있는 관계를 만들어갈 수 있답니다.',
|
||||
],
|
||||
cons: [
|
||||
'둘 다 고집이 있을 수 있어서 의견 충돌 시 양보하는 연습이 필요해요.',
|
||||
'너무 현실적인 면만 추구하다 보면 로맨스가 부족해질 수 있어요.',
|
||||
'변화를 두려워하기보다 함께 새로운 시도를 해보는 것도 좋겠어요.',
|
||||
],
|
||||
advice: '안정감 위에 가끔 달콤한 서프라이즈를 더하면 완벽한 관계가 될 거예요.',
|
||||
},
|
||||
'金_水': {
|
||||
pros: [
|
||||
`${el1Kr}(쇠)이 ${el2Kr}(물)을 만들어내는 관계예요. 깊은 지혜와 감성이 만나는 조합이에요.`,
|
||||
'서로의 내면을 잘 이해하고, 깊은 대화를 나눌 수 있는 사이가 될 거예요.',
|
||||
'원칙과 유연함이 조화를 이루어 균형 잡힌 관계를 만들 수 있어요.',
|
||||
'서로에게 영감을 주고 정서적으로 풍요로운 관계가 될 수 있답니다.',
|
||||
],
|
||||
cons: [
|
||||
'감정 표현 방식이 다를 수 있어요. 직접적으로 마음을 표현하는 연습을 해보세요.',
|
||||
'때로는 너무 이성적이거나 너무 감성적인 면이 부딪힐 수 있어요.',
|
||||
'서로의 감정 표현 스타일을 이해하고 존중하는 것이 중요해요.',
|
||||
],
|
||||
advice: '머리와 가슴의 균형, 이성과 감성의 조화가 이 관계의 매력 포인트예요.',
|
||||
},
|
||||
'水_木': {
|
||||
pros: [
|
||||
`${el2Kr}(물)이 ${el1Kr}(나무)를 키워주는 관계예요. 성장과 발전의 에너지가 넘치는 조합이에요.`,
|
||||
'새로운 것을 시작하고 함께 성장해 나가기에 최적의 파트너예요.',
|
||||
'서로에게 자양분이 되어 끊임없이 발전하는 관계가 될 수 있어요.',
|
||||
'자유롭고 창의적인 에너지가 넘쳐서 함께하면 즐거울 거예요.',
|
||||
],
|
||||
cons: [
|
||||
'방향성 없이 흘러갈 수 있으니 함께 목표를 세우는 것이 중요해요.',
|
||||
'너무 자유로운 성향이 겹치면 책임감이 부족해질 수 있어요.',
|
||||
'각자의 공간을 존중하되, 함께하는 시간도 소중히 여기세요.',
|
||||
],
|
||||
advice: '함께 성장하는 기쁨을 느끼면서, 때로는 뿌리를 내리는 안정감도 챙겨보세요.',
|
||||
},
|
||||
// 동일 오행
|
||||
'same': {
|
||||
pros: [
|
||||
'같은 오행이라 기본적인 가치관과 성향이 비슷해요. 서로를 이해하기 쉬운 관계거든요.',
|
||||
'말하지 않아도 통하는 부분이 많아서 편안한 관계를 유지할 수 있어요.',
|
||||
'취미나 관심사가 비슷해서 함께 즐길 거리가 많을 거예요.',
|
||||
'서로의 마음을 직감적으로 알아차릴 수 있는 특별한 케미가 있어요.',
|
||||
],
|
||||
cons: [
|
||||
'너무 비슷해서 오히려 새로운 자극이 부족할 수 있어요.',
|
||||
'같은 약점을 공유하기 때문에 함께 빠질 수 있는 함정이 있어요.',
|
||||
'때로는 의도적으로 다른 관점을 찾아보는 노력이 필요해요.',
|
||||
],
|
||||
advice: '닮은 점을 즐기되, 각자만의 개성과 차이도 만들어가면 더 풍성한 관계가 될 거예요.',
|
||||
},
|
||||
// 상극
|
||||
'木_土': {
|
||||
pros: [
|
||||
'긴장감이 있지만 그만큼 서로에게 강한 끌림을 느낄 수 있는 관계예요.',
|
||||
'서로 다른 관점을 가지고 있어서 새로운 시각을 배울 수 있어요.',
|
||||
'도전적인 관계이지만 극복할수록 더 단단해지는 사이가 될 거예요.',
|
||||
],
|
||||
cons: [
|
||||
`${el1Kr}(나무)이 ${el2Kr}(흙)을 극하는 관계라 의견 충돌이 생기기 쉬워요.`,
|
||||
'주도권 다툼이 일어날 수 있으니 서로 양보하는 자세가 중요해요.',
|
||||
'상대방을 변화시키려 하기보다 있는 그대로 받아들이는 연습을 해보세요.',
|
||||
'감정이 격해질 때는 일단 한 발 물러서서 냉각 시간을 갖는 것이 좋아요.',
|
||||
],
|
||||
advice: '부딪히는 만큼 성장할 수 있는 관계예요. 서로를 가르치려 하지 말고 배우려는 마음이 중요해요.',
|
||||
},
|
||||
'火_金': {
|
||||
pros: [
|
||||
'강렬한 에너지가 만나는 관계라 서로에게 깊은 인상을 남길 수 있어요.',
|
||||
'서로의 강한 면을 인정하고 존중할 수 있다면 최강의 파트너가 될 수 있어요.',
|
||||
'갈등을 극복한 뒤에는 누구보다 단단한 신뢰가 생기는 관계예요.',
|
||||
],
|
||||
cons: [
|
||||
`${el1Kr}(불)이 ${el2Kr}(쇠)를 녹이는 관계라 갈등이 뜨거울 수 있어요.`,
|
||||
'둘 다 자존심이 강해서 먼저 사과하기 어려울 수 있어요.',
|
||||
'감정적으로 상처를 주기 쉬우니 말 한마디 한마디를 신중하게 하세요.',
|
||||
'서로의 영역을 존중하고 간섭을 줄이는 것이 관계 유지의 비결이에요.',
|
||||
],
|
||||
advice: '불꽃이 튀는 관계이지만, 그 열기를 잘 다스리면 누구보다 강한 유대감을 만들 수 있어요.',
|
||||
},
|
||||
'土_水': {
|
||||
pros: [
|
||||
'서로 다른 성향이지만, 그래서 오히려 배울 점이 많은 관계예요.',
|
||||
'현실적인 면과 유연한 면이 만나 균형을 찾을 수 있는 조합이에요.',
|
||||
'서로의 부족한 점을 채워줄 수 있는 잠재력이 있는 관계거든요.',
|
||||
],
|
||||
cons: [
|
||||
`${el1Kr}(흙)이 ${el2Kr}(물)을 막는 관계라 소통에 장벽이 생기기 쉬워요.`,
|
||||
'고집과 유연함이 부딪히면서 답답함을 느낄 수 있어요.',
|
||||
'서로의 방식을 존중하고, 중간 지점을 찾으려는 노력이 필요해요.',
|
||||
'대화가 막힐 때는 글이나 편지로 마음을 전하는 것도 좋은 방법이에요.',
|
||||
],
|
||||
advice: '서로의 차이를 인정하고 존중하는 것이 이 관계의 가장 큰 과제이자 선물이에요.',
|
||||
},
|
||||
'金_木': {
|
||||
pros: [
|
||||
'서로에게 자극을 주는 관계라 성장의 계기가 될 수 있어요.',
|
||||
'갈등을 잘 해결하면 오히려 더 깊은 이해와 공감이 생기는 사이예요.',
|
||||
'상대방을 통해 자신의 새로운 면을 발견할 수 있는 관계거든요.',
|
||||
],
|
||||
cons: [
|
||||
`${el1Kr}(쇠)이 ${el2Kr}(나무)를 자르는 관계라 비판적인 면이 나올 수 있어요.`,
|
||||
'상대방의 약점을 지적하기보다 장점을 칭찬하는 습관을 들여보세요.',
|
||||
'서로를 통제하려 하면 관계가 힘들어질 수 있으니 자유를 존중해주세요.',
|
||||
'작은 것부터 서로 칭찬하고 감사하는 연습을 해보면 관계가 훨씬 좋아질 거예요.',
|
||||
],
|
||||
advice: '날카로운 면이 있지만, 서로를 다듬어가는 과정에서 보석 같은 관계가 될 수 있어요.',
|
||||
},
|
||||
'水_火': {
|
||||
pros: [
|
||||
'상반된 에너지가 만나서 강한 끌림을 느낄 수 있는 관계예요.',
|
||||
'열정과 차분함이 만나 독특한 균형을 이룰 수 있는 조합이에요.',
|
||||
'서로에게서 완전히 새로운 세계를 경험할 수 있는 흥미로운 관계거든요.',
|
||||
],
|
||||
cons: [
|
||||
`${el1Kr}(물)이 ${el2Kr}(불)을 끄는 관계라 서로의 열정을 꺾을 수 있어요.`,
|
||||
'한쪽이 너무 뜨겁고 한쪽이 너무 차가우면 갈등이 생기기 쉬워요.',
|
||||
'감정의 온도차를 줄이기 위해 서로의 감정을 자주 확인하는 것이 중요해요.',
|
||||
'큰 결정은 충분히 대화한 뒤에 함께 내리는 것이 좋아요.',
|
||||
],
|
||||
advice: '물과 불이 만나면 증기가 되듯, 서로의 에너지를 잘 합치면 엄청난 힘을 발휘할 수 있어요.',
|
||||
},
|
||||
};
|
||||
|
||||
// 상생 관계 매핑
|
||||
if (relation === 'produce') {
|
||||
return interpretations[`${el1}_${produceTarget(el1)}`] || interpretations['same'];
|
||||
}
|
||||
if (relation === 'produced') {
|
||||
return interpretations[`${el2}_${produceTarget(el2)}`] || interpretations['same'];
|
||||
}
|
||||
if (relation === 'same') {
|
||||
return interpretations['same'];
|
||||
}
|
||||
// 상극
|
||||
const key = `${el1}_${overcomeTarget(el1)}`;
|
||||
if (interpretations[key]) return interpretations[key];
|
||||
const reverseKey = `${el2}_${overcomeTarget(el2)}`;
|
||||
if (interpretations[reverseKey]) return interpretations[reverseKey];
|
||||
return interpretations['same'];
|
||||
}
|
||||
|
||||
function produceTarget(el: string): string {
|
||||
const map: Record<string, string> = { '木': '火', '火': '土', '土': '金', '金': '水', '水': '木' };
|
||||
return map[el] || '';
|
||||
}
|
||||
|
||||
function overcomeTarget(el: string): string {
|
||||
const map: Record<string, string> = { '木': '土', '火': '金', '土': '水', '金': '木', '水': '火' };
|
||||
return map[el] || '';
|
||||
}
|
||||
|
||||
// 지지 관계 추가 해석
|
||||
function getBranchInterpretation(branchRel: { sixHarmony: boolean; threeHarmony: boolean; conflict: boolean }) {
|
||||
const extraPros: string[] = [];
|
||||
const extraCons: string[] = [];
|
||||
|
||||
if (branchRel.sixHarmony) {
|
||||
extraPros.push('두 분의 일지가 육합(六合) 관계예요! 천생연분이라고 할 만큼 자연스럽게 잘 맞는 조합이에요.');
|
||||
extraPros.push('만나면 왠지 편안하고 마음이 통하는 느낌을 받으실 거예요.');
|
||||
}
|
||||
if (branchRel.threeHarmony) {
|
||||
extraPros.push('일지가 삼합(三合)에 속해 있어요. 함께 있으면 시너지가 나는 좋은 궁합이에요.');
|
||||
}
|
||||
if (branchRel.conflict) {
|
||||
extraCons.push('일지가 충(沖) 관계에 있어요. 처음에는 강하게 끌리지만, 갈등도 생기기 쉬운 조합이에요.');
|
||||
extraCons.push('충 관계는 변화와 자극이 많아서, 서로 인내하고 이해하려는 노력이 꼭 필요해요.');
|
||||
}
|
||||
|
||||
return { extraPros, extraCons };
|
||||
}
|
||||
|
||||
// 세부 항목별 한 줄 해석
|
||||
function getDetailedComment(category: string, score: number): string {
|
||||
if (category === '연애운') {
|
||||
if (score >= 80) return '함께하면 설렘이 끊이지 않는 로맨틱한 관계가 될 거예요.';
|
||||
if (score >= 65) return '서로에게 좋은 감정을 느끼며 자연스럽게 가까워질 수 있어요.';
|
||||
return '처음에는 어색할 수 있지만, 시간이 지나면 깊은 정이 쌓일 거예요.';
|
||||
}
|
||||
if (category === '결혼운') {
|
||||
if (score >= 80) return '결혼 후에도 서로를 존중하며 행복한 가정을 꾸릴 수 있어요.';
|
||||
if (score >= 65) return '일상의 소소한 행복을 함께 나누며 안정적인 결혼생활이 가능해요.';
|
||||
return '결혼생활에서는 서로의 역할 분담과 소통이 특히 중요한 커플이에요.';
|
||||
}
|
||||
if (category === '금전운') {
|
||||
if (score >= 80) return '함께 재물을 모으고 불리는 데 시너지가 나는 조합이에요.';
|
||||
if (score >= 65) return '경제적으로 안정적인 파트너십을 만들어갈 수 있어요.';
|
||||
return '금전 문제에 대해 미리 충분히 대화하고 합의하는 것이 중요해요.';
|
||||
}
|
||||
// 사업운
|
||||
if (score >= 80) return '비즈니스 파트너로도 훌륭한 조합이에요. 함께하면 성공 가능성이 높아요.';
|
||||
if (score >= 65) return '각자의 강점을 살려 역할을 나누면 좋은 결과를 만들 수 있어요.';
|
||||
return '사업적으로는 신중한 접근이 필요해요. 역할과 책임을 명확히 하세요.';
|
||||
}
|
||||
|
||||
export default async function CompatibilityResultPage({ searchParams }: PageProps) {
|
||||
const params = await searchParams;
|
||||
const { year1, month1, day1, hour1, gender1, year2, month2, day2, hour2, gender2 } = params;
|
||||
|
||||
// Person 1 Saju
|
||||
const saju1 = calculateSaju(
|
||||
parseInt(year1),
|
||||
parseInt(month1),
|
||||
parseInt(day1),
|
||||
hour1 ? parseInt(hour1) : null,
|
||||
gender1
|
||||
);
|
||||
const saju1 = calculateSaju(parseInt(year1), parseInt(month1), parseInt(day1), hour1 ? parseInt(hour1) : null, gender1);
|
||||
const saju2 = calculateSaju(parseInt(year2), parseInt(month2), parseInt(day2), hour2 ? parseInt(hour2) : null, gender2);
|
||||
|
||||
// Person 2 Saju
|
||||
const saju2 = calculateSaju(
|
||||
parseInt(year2),
|
||||
parseInt(month2),
|
||||
parseInt(day2),
|
||||
hour2 ? parseInt(hour2) : null,
|
||||
gender2
|
||||
);
|
||||
const element1 = saju1.day.element;
|
||||
const element2 = saju2.day.element;
|
||||
const branch1 = saju1.day.branch;
|
||||
const branch2 = saju2.day.branch;
|
||||
|
||||
const elementRelation = getElementRelation(element1, element2);
|
||||
const branchRel = getBranchRelation(branch1, branch2);
|
||||
|
||||
// 궁합 점수 계산
|
||||
const calculateCompatibility = () => {
|
||||
let score = 50; // 기본 점수
|
||||
let score = 50;
|
||||
if (element1 === element2) score += 10;
|
||||
else if (elementRelation === 'produce' || elementRelation === 'produced') score += 25;
|
||||
else score -= 10; // overcome/overcomed
|
||||
|
||||
// 오행 상생/상극 관계
|
||||
const element1 = saju1.day.element;
|
||||
const element2 = saju2.day.element;
|
||||
|
||||
const produceMap: { [key: string]: string } = {
|
||||
'木': '火', '火': '土', '土': '金', '金': '水', '水': '木'
|
||||
};
|
||||
const overcomeMap: { [key: string]: string } = {
|
||||
'木': '土', '火': '金', '土': '水', '金': '木', '水': '火'
|
||||
};
|
||||
|
||||
// 같은 오행: 보통
|
||||
if (element1 === element2) {
|
||||
score += 10;
|
||||
}
|
||||
// 상생 관계: 매우 좋음
|
||||
else if (produceMap[element1] === element2 || produceMap[element2] === element1) {
|
||||
score += 25;
|
||||
}
|
||||
// 상극 관계: 주의 필요
|
||||
else if (overcomeMap[element1] === element2 || overcomeMap[element2] === element1) {
|
||||
score -= 10;
|
||||
}
|
||||
|
||||
// 지지 삼합/육합 관계 확인
|
||||
const branch1 = saju1.day.branch;
|
||||
const branch2 = saju2.day.branch;
|
||||
|
||||
// 육합 (六合) - 특별히 좋은 궁합
|
||||
const sixHarmony: { [key: string]: string } = {
|
||||
'子': '丑', '丑': '子',
|
||||
'寅': '亥', '亥': '寅',
|
||||
'卯': '戌', '戌': '卯',
|
||||
'辰': '酉', '酉': '辰',
|
||||
'巳': '申', '申': '巳',
|
||||
'午': '未', '未': '午'
|
||||
};
|
||||
|
||||
if (sixHarmony[branch1] === branch2) {
|
||||
score += 20;
|
||||
}
|
||||
|
||||
// 삼합 (三合) - 좋은 궁합
|
||||
const threeHarmony = [
|
||||
['申', '子', '辰'], // 수국
|
||||
['寅', '午', '戌'], // 화국
|
||||
['亥', '卯', '未'], // 목국
|
||||
['巳', '酉', '丑'] // 금국
|
||||
];
|
||||
|
||||
for (const harmony of threeHarmony) {
|
||||
if (harmony.includes(branch1) && harmony.includes(branch2)) {
|
||||
score += 15;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 충 (沖) - 나쁜 궁합
|
||||
const conflict: { [key: string]: string } = {
|
||||
'子': '午', '午': '子',
|
||||
'丑': '未', '未': '丑',
|
||||
'寅': '申', '申': '寅',
|
||||
'卯': '酉', '酉': '卯',
|
||||
'辰': '戌', '戌': '辰',
|
||||
'巳': '亥', '亥': '巳'
|
||||
};
|
||||
|
||||
if (conflict[branch1] === branch2) {
|
||||
score -= 20;
|
||||
}
|
||||
if (branchRel.sixHarmony) score += 20;
|
||||
if (branchRel.threeHarmony) score += 15;
|
||||
if (branchRel.conflict) score -= 20;
|
||||
|
||||
return Math.min(100, Math.max(0, score));
|
||||
};
|
||||
@@ -144,13 +368,25 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
return 'from-gray-400 to-gray-500';
|
||||
};
|
||||
|
||||
// 세부 궁합 점수
|
||||
// Deterministic seed for detailed scores
|
||||
const seed = `${year1}${month1}${day1}${year2}${month2}${day2}`;
|
||||
const detailedScores = [
|
||||
{ name: '연애운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💑' },
|
||||
{ name: '결혼운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💍' },
|
||||
{ name: '금전운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💰' },
|
||||
{ name: '사업운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💼' },
|
||||
].map(item => ({ ...item, score: Math.min(100, Math.max(0, item.score)) }));
|
||||
{ name: '연애운', score: compatibilityScore + seededOffset(seed, 1), icon: '💑' },
|
||||
{ name: '결혼운', score: compatibilityScore + seededOffset(seed, 2), icon: '💍' },
|
||||
{ name: '금전운', score: compatibilityScore + seededOffset(seed, 3), icon: '💰' },
|
||||
{ name: '사업운', score: compatibilityScore + seededOffset(seed, 4), icon: '💼' },
|
||||
].map(item => ({
|
||||
...item,
|
||||
score: Math.min(100, Math.max(0, item.score)),
|
||||
comment: getDetailedComment(item.name, Math.min(100, Math.max(0, compatibilityScore + seededOffset(seed, ['연애운', '결혼운', '금전운', '사업운'].indexOf(item.name) + 1)))),
|
||||
}));
|
||||
|
||||
// 오행 기반 상세 해석
|
||||
const interp = getElementInterpretation(element1, element2, elementRelation);
|
||||
const branchInterp = getBranchInterpretation(branchRel);
|
||||
|
||||
const allPros = [...interp.pros, ...branchInterp.extraPros];
|
||||
const allCons = [...interp.cons, ...branchInterp.extraCons];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-pink-50 via-purple-50 to-indigo-50">
|
||||
@@ -162,18 +398,8 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
🔮 사주보기
|
||||
</Link>
|
||||
<div className="flex gap-4">
|
||||
<Link
|
||||
href="/compatibility"
|
||||
className="text-gray-700 hover:text-pink-600 transition font-medium"
|
||||
>
|
||||
다시 보기
|
||||
</Link>
|
||||
<Link
|
||||
href="/"
|
||||
className="text-gray-700 hover:text-pink-600 transition font-medium"
|
||||
>
|
||||
처음으로
|
||||
</Link>
|
||||
<Link href="/compatibility" className="text-gray-700 hover:text-pink-600 transition font-medium">다시 보기</Link>
|
||||
<Link href="/" className="text-gray-700 hover:text-pink-600 transition font-medium">처음으로</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -183,27 +409,18 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
<div id="pdf-content" className="max-w-6xl mx-auto px-4 py-12">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
|
||||
💕 궁합 결과
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600">
|
||||
두 사람의 사주팔자를 비교한 결과입니다
|
||||
</p>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">💕 궁합 결과</h1>
|
||||
<p className="text-xl text-gray-600">두 사람의 사주팔자를 비교한 결과입니다</p>
|
||||
</div>
|
||||
|
||||
{/* 두 사람 정보 */}
|
||||
<div className="grid md:grid-cols-2 gap-6 mb-12">
|
||||
{/* Person 1 */}
|
||||
<div className="bg-gradient-to-br from-pink-500 to-pink-600 rounded-2xl shadow-xl p-8 text-white">
|
||||
<div className="text-center mb-6">
|
||||
<div className="text-5xl mb-3">👤</div>
|
||||
<h3 className="text-2xl font-bold">첫 번째 사람</h3>
|
||||
<p className="text-pink-100 mt-2">
|
||||
{saju1.birthDate.year}년 {saju1.birthDate.month}월 {saju1.birthDate.day}일
|
||||
</p>
|
||||
<p className="text-pink-100">
|
||||
{gender1 === 'male' ? '남성' : '여성'}
|
||||
</p>
|
||||
<p className="text-pink-100 mt-2">{saju1.birthDate.year}년 {saju1.birthDate.month}월 {saju1.birthDate.day}일</p>
|
||||
<p className="text-pink-100">{gender1 === 'male' ? '남성' : '여성'}</p>
|
||||
</div>
|
||||
<div className="bg-white/20 backdrop-blur-sm rounded-xl p-4">
|
||||
<p className="text-center mb-2 font-semibold">일간 (日干)</p>
|
||||
@@ -212,24 +429,17 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
<span className="text-2xl ml-2">({saju1.day.stemKr})</span>
|
||||
</div>
|
||||
<p className="text-center mt-2 text-pink-100">
|
||||
{saju1.day.element} ({['木', '火', '土', '金', '水'].indexOf(saju1.day.element) >= 0
|
||||
? ['목', '화', '토', '금', '수'][['木', '火', '土', '金', '水'].indexOf(saju1.day.element)]
|
||||
: ''})
|
||||
{element1} ({elementKrMap[element1] || ''})
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Person 2 */}
|
||||
<div className="bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl shadow-xl p-8 text-white">
|
||||
<div className="text-center mb-6">
|
||||
<div className="text-5xl mb-3">👤</div>
|
||||
<h3 className="text-2xl font-bold">두 번째 사람</h3>
|
||||
<p className="text-purple-100 mt-2">
|
||||
{saju2.birthDate.year}년 {saju2.birthDate.month}월 {saju2.birthDate.day}일
|
||||
</p>
|
||||
<p className="text-purple-100">
|
||||
{gender2 === 'male' ? '남성' : '여성'}
|
||||
</p>
|
||||
<p className="text-purple-100 mt-2">{saju2.birthDate.year}년 {saju2.birthDate.month}월 {saju2.birthDate.day}일</p>
|
||||
<p className="text-purple-100">{gender2 === 'male' ? '남성' : '여성'}</p>
|
||||
</div>
|
||||
<div className="bg-white/20 backdrop-blur-sm rounded-xl p-4">
|
||||
<p className="text-center mb-2 font-semibold">일간 (日干)</p>
|
||||
@@ -238,9 +448,7 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
<span className="text-2xl ml-2">({saju2.day.stemKr})</span>
|
||||
</div>
|
||||
<p className="text-center mt-2 text-purple-100">
|
||||
{saju2.day.element} ({['木', '火', '土', '金', '水'].indexOf(saju2.day.element) >= 0
|
||||
? ['목', '화', '토', '금', '수'][['木', '火', '土', '金', '水'].indexOf(saju2.day.element)]
|
||||
: ''})
|
||||
{element2} ({elementKrMap[element2] || ''})
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -259,10 +467,7 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
</div>
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<div className="w-full bg-white/30 rounded-full h-4">
|
||||
<div
|
||||
className="bg-white h-4 rounded-full transition-all duration-1000"
|
||||
style={{ width: `${compatibilityScore}%` }}
|
||||
></div>
|
||||
<div className="bg-white h-4 rounded-full transition-all duration-1000" style={{ width: `${compatibilityScore}%` }}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -281,89 +486,38 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
</div>
|
||||
<span className="text-2xl font-bold text-pink-600">{item.score}점</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-3">
|
||||
<div className="w-full bg-gray-200 rounded-full h-3 mb-3">
|
||||
<div
|
||||
className="bg-gradient-to-r from-pink-500 to-purple-500 h-3 rounded-full transition-all duration-500"
|
||||
style={{ width: `${item.score}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600">{item.comment}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 궁합 해석 */}
|
||||
<div className="grid md:grid-cols-2 gap-8 mb-8">
|
||||
{/* 장점 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
||||
<span className="text-3xl mr-3">✅</span>
|
||||
두 사람의 장점
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<li className="flex items-start">
|
||||
<span className="text-pink-600 mr-2">•</span>
|
||||
<span>서로의 부족한 점을 잘 보완해줄 수 있습니다.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-pink-600 mr-2">•</span>
|
||||
<span>대화와 소통이 원활하게 이루어질 수 있습니다.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-pink-600 mr-2">•</span>
|
||||
<span>함께 있을 때 편안함을 느낄 수 있습니다.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 주의점 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
||||
<span className="text-3xl mr-3">⚠️</span>
|
||||
주의할 점
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<li className="flex items-start">
|
||||
<span className="text-purple-600 mr-2">•</span>
|
||||
<span>서로의 가치관 차이를 이해하려는 노력이 필요합니다.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-purple-600 mr-2">•</span>
|
||||
<span>감정적인 대화보다는 이성적인 대화를 나누세요.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-purple-600 mr-2">•</span>
|
||||
<span>작은 문제도 소통으로 해결하려는 자세가 중요합니다.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 조언 */}
|
||||
<div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-2xl shadow-lg p-8 text-white mb-8">
|
||||
<h3 className="text-2xl font-bold mb-4 text-center">💡 조언</h3>
|
||||
<p className="text-lg leading-relaxed text-center">
|
||||
궁합은 참고사항일 뿐입니다. 서로를 이해하고 존중하며 노력한다면
|
||||
어떤 궁합이든 행복한 관계를 만들 수 있습니다.
|
||||
사주는 가능성을 보여줄 뿐, 최종 결정은 두 사람의 마음과 노력에 달려있습니다.
|
||||
</p>
|
||||
</div>
|
||||
{/* 궁합 상세 해석 - 블러 잠금 영역 */}
|
||||
<CompatibilityDetailUnlock
|
||||
allPros={allPros}
|
||||
allCons={allCons}
|
||||
advice={interp.advice}
|
||||
element1={element1}
|
||||
element2={element2}
|
||||
element1Kr={elementKrMap[element1] || ''}
|
||||
element2Kr={elementKrMap[element2] || ''}
|
||||
/>
|
||||
|
||||
{/* 다른 메뉴 */}
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<Link
|
||||
href="/compatibility"
|
||||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group"
|
||||
>
|
||||
<Link href="/compatibility" className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group">
|
||||
<div className="text-4xl mb-3">💕</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-2">다시 보기</h3>
|
||||
<p className="text-gray-600 text-sm">다른 궁합 확인하기</p>
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href="/"
|
||||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group"
|
||||
>
|
||||
<Link href="/" className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group">
|
||||
<div className="text-4xl mb-3">📜</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-2">사주 보기</h3>
|
||||
<p className="text-gray-600 text-sm">내 사주 확인하기</p>
|
||||
@@ -389,9 +543,7 @@ export default async function CompatibilityResultPage({ searchParams }: PageProp
|
||||
<div className="text-2xl font-bold mb-4 bg-gradient-to-r from-pink-400 to-purple-400 bg-clip-text text-transparent">
|
||||
🔮 사주보기
|
||||
</div>
|
||||
<p className="text-gray-400 mb-6">
|
||||
쟁승메이드가 제공하는 무료 사주 서비스
|
||||
</p>
|
||||
<p className="text-gray-400 mb-6">쟁승메이드가 제공하는 무료 사주 서비스</p>
|
||||
<div className="text-sm text-gray-500">
|
||||
<p>문의: bgg8988@gmail.com | <a href="https://jaengseung-made.com" target="_blank" rel="noopener noreferrer" className="hover:text-pink-400">쟁승메이드</a></p>
|
||||
<p className="mt-2">© 2025 쟁승메이드. All rights reserved.</p>
|
||||
|
||||
Reference in New Issue
Block a user