import React, { useMemo } from 'react';
import {
fmtKST, Ball, NumberRow, copyNumbers,
buildMetricsFromFrequency, BEST_PICKS_DEFAULT_SHOW,
} from '../lottoUtils';
import useLottoData from '../hooks/useLottoData';
import useManualRecommend from '../hooks/useManualRecommend';
import MetricBlock from '../components/MetricBlock';
import FrequencyChart from '../components/FrequencyChart';
import PerformanceBanner from '../components/PerformanceBanner';
import CombinedRecommendPanel from '../components/CombinedRecommendPanel';
import ReportPanel from '../components/ReportPanel';
import PersonalAnalysisPanel from '../components/PersonalAnalysisPanel';
export default function AnalysisTab() {
const ld = useLottoData();
const mr = useManualRecommend();
const overallMetrics = useMemo(() => buildMetricsFromFrequency(ld.stats?.frequency), [ld.stats]);
const visibleBestPicks = ld.bestPicksExpanded ? ld.bestPicks : ld.bestPicks.slice(0, BEST_PICKS_DEFAULT_SHOW);
const error = ld.error || mr.error;
const clearError = () => { ld.setError(''); mr.setError(''); };
return (
<>
{error ? (
) : null}
{/* 신뢰도 배너 */}
{/* 종합 추론 번호 추천 */}
{/* 최신 회차 + 시뮬레이션 추천 */}
{/* Latest Draw */}
Latest Draw
최신 회차
최신 회차와 번호를 빠르게 확인할 수 있습니다.
{ld.loading.latest ? 로딩 중 : null}
{ld.latest ? (
<>
{ld.latest.drawNo}회
{ld.latest.date}
보너스 {ld.latest.bonus}
{overallMetrics && (
)}
>
) : (
최신 회차 데이터가 없습니다.
)}
{/* Simulation Picks */}
Simulation Picks
시뮬레이션 추천
하루 6회 몬테카를로 시뮬레이션으로 선별된 최적 번호입니다.
{ld.loading.bestPicks ? 로딩 중 : null}
{ld.simulating ? 분석 중 : null}
{ld.simResult && (
완료: {ld.simResult.total_generated?.toLocaleString()}개 후보 → 상위 {ld.simResult.best_n_saved}개 저장
최고 점수 {((ld.simResult.best_score ?? 0) * 100).toFixed(1)}% / 평균 {((ld.simResult.avg_score ?? 0) * 100).toFixed(1)}%
)}
{ld.bestPicks.length === 0 ? (
{ld.loading.bestPicks ? '불러오는 중...' : "시뮬레이션 결과가 없습니다. '지금 실행'으로 시작하세요."}
) : (
<>
{visibleBestPicks.map((pick) => (
#{pick.rank}
{((pick.score_total ?? 0) * 100).toFixed(1)}%
))}
{ld.bestPicks.length > BEST_PICKS_DEFAULT_SHOW && (
)}
갱신: {fmtKST(ld.bestPicks[0]?.created_at) || '-'}
{ld.bestPicks[0]?.based_on_draw ? ` · ${ld.bestPicks[0].based_on_draw}회 기준` : ''}
>
)}
{/* 이번 주 공략 리포트 */}
{/* 통계 분석 */}
Analysis
통계 분석
빈도, Z-score, 갭 분석으로 번호를 분류합니다.
{ld.loading.analysis ? 로딩 중 : null}
{ld.analysis ? (
🔥 핫 번호 출현 빈도 상위 10
{(ld.analysis.hot_numbers ?? []).map((n) => )}
🧊 콜드 번호 출현 빈도 하위 10
{(ld.analysis.cold_numbers ?? []).map((n) => )}
⏰ 오버듀 번호 오래 안 나온 번호 (회차 수)
{(ld.analysis.overdue_numbers ?? []).map((n) => {
const stat = (ld.analysis.number_stats ?? []).find((s) => s.number === n);
return (
{stat?.gap ?? '-'}회
);
})}
역대 합계 평균 {ld.analysis.mean_sum}
표준편차 ±{ld.analysis.std_sum}
분석 회차 {ld.analysis.total_draws?.toLocaleString()}
홀수 3:짝수 3 확률{' '}
{ld.analysis.odd_distribution?.['3'] ? `${ld.analysis.odd_distribution['3']}%` : '-'}
) : (
{ld.loading.analysis ? '불러오는 중...' : '통계 분석 데이터가 없습니다.'}
)}
{/* 전체 번호 분포 */}
Distribution
전체 회차 번호 분포
1~45번 번호가 등장한 횟수를 기준으로 분포를 표시합니다.
{ld.statsLoading ? 로딩 중 : null}
{ld.stats?.total_draws ? (
{ld.stats.total_draws}회차
) : null}
{ld.statsError ? {ld.statsError}
: null}
{ld.stats ? (
) : (
통계 데이터를 불러오지 못했습니다.
)}
{/* 내 번호 패턴 */}
{/* 수동 추천 */}
Manual Recommendation
수동 추천
파라미터를 직접 조정해 번호를 추천받을 수 있습니다.
{mr.loading.recommend ? 계산 중 : null}
{mr.presets.map((preset) => (
))}
{mr.result ? (
추천 ID #{mr.result.id}
기준 회차 {mr.result.based_on_latest_draw ?? '-'}
{mr.result.numbers &&
}
{mr.historyMetrics && (
)}
{Array.isArray(mr.result.items) && mr.result.items.length ? (
추천 후보 보기
{mr.result.items.map((item, idx) => (
후보 #{item.id ?? idx + 1}
기준 회차 {item.based_on_draw ?? '-'}
{item.metrics &&
}
))}
) : null}
{mr.result.explain && (
설명 보기
{JSON.stringify(mr.result.explain, null, 2)}
)}
) : (
아직 추천 결과가 없습니다.
)}
{/* 추천 히스토리 */}
History
추천 히스토리
수동 추천 결과를 모아서 확인할 수 있습니다.
{mr.history.length}건
{mr.history.length > 5 && (
)}
{mr.loading.history ? 불러오는 중...
: null}
{mr.history.length === 0 ? (
저장된 히스토리가 없습니다.
) : (
{mr.visibleHistory.map((item) => (
#{item.id}
{fmtKST(item.created_at)}
기준 회차 {item.based_on_draw ?? '-'}
window={item.params?.recent_window}, weight={item.params?.recent_weight},
avoid_k={item.params?.avoid_recent_k}
))}
)}
>
);
}