`;
}
}
};
// ===================================
// 동적 번호 프리뷰 시스템
// ===================================
/* 동적 번호 프리뷰 관리 */
const preview = {
// 프리뷰 시작
start: function() {
if (previewInterval) return;
const container = document.getElementById('lottoNumbers');
if (!container) return;
// 초기 프리뷰 HTML 생성
container.innerHTML = `
${Array.from({length: 6}, (_, i) => `
${Math.floor(Math.random() * 45) + 1}
`).join('')}
`;
// 정기적으로 번호 변경
previewInterval = setInterval(() => {
if (!isGenerating) {
this.updateNumbers();
}
}, 800);
logger.log('동적 번호 프리뷰 시작됨');
},
// 번호 업데이트
updateNumbers: function() {
const balls = document.querySelectorAll('.lotto-preview .lotto-ball');
balls.forEach((ball, index) => {
// 번호 변경 애니메이션 적용
ball.classList.add('number-changing');
setTimeout(() => {
const newNumber = Math.floor(Math.random() * 45) + 1;
ball.textContent = newNumber;
ball.className = `lotto-ball ${this.getNumberClass(newNumber)} number-changing`;
setTimeout(() => {
ball.classList.remove('number-changing');
}, 300);
}, 300);
});
},
// 번호 범위에 따른 클래스 반환
getNumberClass: function(num) {
if (num <= 10) return 'number-1-10';
if (num <= 20) return 'number-11-20';
if (num <= 30) return 'number-21-30';
if (num <= 40) return 'number-31-40';
return 'number-41-45';
},
// 프리뷰 정지
stop: function() {
if (previewInterval) {
clearInterval(previewInterval);
previewInterval = null;
logger.log('동적 번호 프리뷰 정지됨');
}
}
};
// ===================================
// 저장소 관리
// ===================================
/* localStorage 관련 기능 */
const storage = {
// 히스토리 저장
saveHistory: function(history) {
try {
localStorage.setItem('lottoNumberHistory', JSON.stringify(history));
logger.log('히스토리가 localStorage에 저장됨', history.length);
} catch (error) {
logger.error('localStorage 저장 실패', error);
}
},
// 히스토리 불러오기
loadHistory: function() {
try {
const savedHistory = localStorage.getItem('lottoNumberHistory');
if (savedHistory) {
const parsed = JSON.parse(savedHistory);
if (Array.isArray(parsed) && parsed.every(item =>
item && Array.isArray(item.numbers) && item.numbers.length > 0)) {
logger.log('localStorage에서 히스토리 로드됨', parsed.length);
return parsed;
} else {
logger.error('유효하지 않은 히스토리 데이터');
localStorage.removeItem('lottoNumberHistory');
}
}
} catch (error) {
logger.error('localStorage 로드 실패', error);
localStorage.removeItem('lottoNumberHistory');
}
return [];
},
// 히스토리 초기화
clearHistory: function() {
try {
localStorage.removeItem('lottoNumberHistory');
logger.log('히스토리가 초기화됨');
numberHistory = [];
} catch (error) {
logger.error('localStorage 삭제 실패', error);
}
}
};
// ===================================
// 번호 저장 및 공개 로그 기능
// ===================================
/* 번호 저장 기능 */
const numberSaver = {
// 번호 저장
async saveNumber(numbers, userInitial = '') {
try {
console.log('🔄 numberSaver.saveNumber 호출됨');
console.log('📤 요청 데이터:', { numbers, userInitial });
const requestData = {
numbers: numbers,
user_initial: userInitial
};
console.log('📤 실제 전송 데이터:', requestData);
// fetch 요청에 타임아웃 추가
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10초 타임아웃
const response = await fetch('api/save_number.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache'
},
body: JSON.stringify(requestData),
signal: controller.signal
});
clearTimeout(timeoutId);
console.log('📥 응답 상태:', response.status, response.statusText);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
}
const responseText = await response.text();
console.log('📥 원본 응답 텍스트:', responseText);
// 응답이 비어있는지 확인
if (!responseText || responseText.trim() === '') {
throw new Error('서버에서 빈 응답을 반환했습니다');
}
let data;
try {
data = JSON.parse(responseText);
console.log('📥 파싱된 응답:', data);
} catch (parseError) {
console.error('❌ JSON 파싱 실패:', parseError);
console.error('❌ 원본 텍스트:', responseText);
// HTML 응답인 경우 (에러 페이지 등)
if (responseText.includes(' {
if (typeof publicLog !== 'undefined' && publicLog.refresh) {
publicLog.refresh();
}
}, 1500);
return data;
} else {
console.error('❌ 저장 실패:', data.message);
return { success: false, message: data.message || '알 수 없는 서버 오류' };
}
} catch (error) {
console.error('❌ numberSaver 오류:', error);
// 구체적인 오류 메시지 반환
let errorMessage = '알 수 없는 오류가 발생했습니다';
if (error.name === 'AbortError') {
errorMessage = '요청이 시간 초과되었습니다';
} else if (error.message.includes('fetch')) {
errorMessage = '네트워크 연결 오류입니다';
} else {
errorMessage = error.message;
}
return { success: false, message: errorMessage };
}
}
};
/* 공개 로그 관리 */
const publicLog = {
/* 공개 로그 조회 */
async refresh() {
try {
console.log('🔄 공개 로그 새로고침 시작');
// 타임스탬프 추가로 캐시 방지
const response = await fetch(`api/get_public_log.php?t=${Date.now()}`);
const data = await response.json();
if (data.success) {
this.displayLogs(data.logs);
console.log('✅ 공개 로그 새로고침 성공');
} else {
this.displayError(data.message);
console.error('❌ 공개 로그 조회 실패:', data.message);
}
} catch (error) {
logger.error('공개 로그 조회 실패', error);
this.displayError('로그를 불러오는데 실패했습니다.');
}
},
// 로그 표시
displayLogs(logs) {
const container = document.getElementById('publicLog');
if (!container) {
console.log('publicLog 컨테이너를 찾을 수 없음');
return;
}
if (logs.length === 0) {
container.innerHTML = `
아직 생성된 번호가 없습니다
`;
return;
}
// 실시간 번호 생성로그
const logHtml = logs.map(log => {
let winningInfo = '';
let numbersHtml = '';
if (log.winning) {
// 당첨 정보가 있는 경우
numbersHtml = log.numbers.map(num => {
const isWinning = log.winning.winningNumbers.includes(num);
const baseClass = preview.getNumberClass(num);
const winningClass = isWinning ? 'winning-number' : '';
return `${num}`;
}).join('');
winningInfo = `${log.winning.rank}등!`;
} else {
// 일반 번호 표시
numbersHtml = log.numbers.map(num => {
return `${num}`;
}).join('');
}
return `
`;
}).join('');
},
// 로딩 표시
displayLoading(containerId) {
const container = document.getElementById(containerId);
if (container) {
container.innerHTML = `
Loading...
`;
}
},
// 에러 메시지 표시
displayError(containerId, message) {
const container = document.getElementById(containerId);
if (container) {
container.innerHTML = `
${message}
`;
}
}
};
// ===================================
// 당첨번호 정보 로드 (기존 API 활용)
// ===================================
/* 당첨번호 정보 로드 */
async function loadCurrentLottoInfo() {
try {
console.log('🔄 당첨번호 정보 로드 시작');
// 기존 get_latest_round_stats.php 활용
const response = await fetch(`api/get_latest_round_stats.php?t=${Date.now()}`);
const data = await response.json();
if (data.success && data.round_info) {
updateCurrentLottoInfoUI(data.round_info);
console.log('✅ 당첨번호 정보 로드 성공');
} else {
displayCurrentLottoInfoError(data.message || '당첨 정보를 불러올 수 없습니다.');
console.error('❌ 당첨번호 정보 로드 실패:', data.message);
}
} catch (error) {
logger.error('당첨번호 정보 로드 실패', error);
displayCurrentLottoInfoError('당첨 정보를 불러오는데 실패했습니다.');
}
}
/* 당첨번호 정보 UI 업데이트 */
function updateCurrentLottoInfoUI(roundInfo) {
const container = document.getElementById('currentLottoInfo');
if (!container) return;
const winningNumbers = roundInfo.winning_numbers.map(num =>
`${num}`
).join('');
const bonusNumber = `${roundInfo.bonus_number}`;
// 1등 당첨 정보만 표시
let firstPrizeHtml = '';
if (roundInfo.prize_info && roundInfo.prize_info.first) {
const firstPrize = roundInfo.prize_info.first;
firstPrizeHtml = `
1등 당첨 정보
${firstPrize.winners}명
당첨자 수
${firstPrize.amount}
당첨금액
`;
} else {
firstPrizeHtml = `
undefined명
1등 당첨자 수
undefined
1등 당첨금액
당첨금 정보는 동행복권 공식 발표 후 업데이트됩니다.
`;
}
const html = `
${roundInfo.round}회 당첨결과
(${roundInfo.draw_date} 추첨)
${winningNumbers}
당첨번호
+
${bonusNumber}
보너스
${firstPrizeHtml}
`;
container.innerHTML = html;
// 당첨금액 텍스트 길이에 따른 클래스 추가
setTimeout(() => {
const prizeValues = document.querySelectorAll('.prize-value');
prizeValues.forEach(element => {
const text = element.textContent || '';
const length = text.length;
// 텍스트 길이에 따른 클래스 추가
if (length > 15) {
element.setAttribute('data-length', 'very-long');
element.classList.add('prize-value-responsive');
} else if (length > 10) {
element.setAttribute('data-length', 'long');
element.classList.add('prize-value-responsive');
}
// 제목 속성에 전체 텍스트 추가 (접근성)
element.setAttribute('title', text);
// 당첨금액인 경우 특별 처리
if (element.classList.contains('text-success')) {
if (text.includes('억') || text.includes('조')) {
element.classList.add('prize-value-responsive');
}
}
});
}, 100);
}
/* 볼 색상 클래스 반환 */
function getBallColor(num) {
if (num <= 10) return '1-10';
if (num <= 20) return '11-20';
if (num <= 30) return '21-30';
if (num <= 40) return '31-40';
return '41-45';
}
/* 당첨번호 정보 에러 표시 */
function displayCurrentLottoInfoError(message) {
const container = document.getElementById('currentLottoInfo');
if (container) {
container.innerHTML = `
${message}
`;
}
}
// ===================================
// 당첨 통계 관련 함수
// ===================================
/* 당첨 통계 로드 함수 */
async function loadWinningStats() {
try {
console.log('🔄 주간 당첨 통계 로드 시작');
// 새로운 주간 통계 API 호출
const response = await fetch(`api/get_weekly_winning_stats.php?t=${Date.now()}`);
const data = await response.json();
if (data.success) {
updateWeeklyWinningStatsUI(data);
console.log('✅ 주간 당첨 통계 로드 성공');
} else {
displayWeeklyStatsError(data.message);
console.error('❌ 주간 당첨 통계 로드 실패:', data.message);
}
} catch (error) {
logger.error('주간 당첨 통계 로드 실패', error);
displayWeeklyStatsError('주간 통계를 불러오는데 실패했습니다.');
}
}
/* 등급별 당첨 현황 로드 함수 */
async function loadLatestRoundWinningStats() {
try {
console.log('🔄 최신 회차 등급별 당첨 현황 로드 시작');
// 최신 완료된 회차 정보 조회
const response = await fetch(`api/get_latest_round_stats.php?t=${Date.now()}`);
const data = await response.json();
if (data.success) {
updateLatestRoundStatsUI(data);
console.log('✅ 최신 회차 등급별 당첨 현황 로드 성공');
} else {
displayLatestRoundStatsError(data.message);
console.error('❌ 최신 회차 등급별 당첨 현황 로드 실패:', data.message);
}
} catch (error) {
logger.error('최신 회차 등급별 당첨 현황 로드 실패', error);
displayLatestRoundStatsError('등급별 당첨 현황을 불러오는데 실패했습니다.');
}
}
/* 최신 회차 등급별 당첨 현황 UI 업데이트 */
function updateLatestRoundStatsUI(data) {
const container = document.getElementById('weeklyRankStats');
if (!container) return;
const stats = data.stats;
const roundInfo = data.round_info;
let html = `
${roundInfo.round}회 명예의 전당
(${roundInfo.draw_date} 추첨 기준)
`;
// 회차 정보가 있는 경우 당첨번호 표시
if (roundInfo.winning_numbers) {
html += `
`;
// 기존 모달 완전히 제거
const existingModal = document.getElementById('roundWinnerModal');
if (existingModal) {
const modalInstance = bootstrap.Modal.getInstance(existingModal);
if (modalInstance) {
modalInstance.dispose();
}
existingModal.remove();
}
// 남아있는 배경 제거
const backdrops = document.querySelectorAll('.modal-backdrop');
backdrops.forEach(backdrop => backdrop.remove());
// 새 모달 추가
document.body.insertAdjacentHTML('beforeend', modalHtml);
// 새 모달 인스턴스 생성
const newModal = new bootstrap.Modal(document.getElementById('roundWinnerModal'), {
backdrop: true,
keyboard: true,
focus: true
});
// 모달 이벤트 리스너 추가
const modalElement = document.getElementById('roundWinnerModal');
modalElement.addEventListener('hidden.bs.modal', function () {
// 모달이 완전히 닫힌 후 정리
const modalInstance = bootstrap.Modal.getInstance(this);
if (modalInstance) {
modalInstance.dispose();
}
this.remove();
// 남은 배경 정리
const remainingBackdrops = document.querySelectorAll('.modal-backdrop');
remainingBackdrops.forEach(backdrop => backdrop.remove());
// body 스타일 정리
document.body.classList.remove('modal-open');
document.body.style.overflow = '';
document.body.style.paddingRight = '';
});
newModal.show();
}
/* 회차 필터 클릭 핸들러 (모달 중복 방지) */
async function handleRoundFilterClick(round, rank = null) {
// 클릭 시 잠시 비활성화
const clickedButton = event.target;
const originalText = clickedButton.textContent;
clickedButton.disabled = true;
clickedButton.textContent = '로딩...';
try {
await showRoundWinnerDetails(round, rank);
} catch (error) {
console.error('필터 변경 실패:', error);
} finally {
// 버튼 복원 (혹시 모달이 교체되어도 안전하게)
setTimeout(() => {
if (clickedButton) {
clickedButton.disabled = false;
clickedButton.textContent = originalText;
}
}, 300);
}
}
// ===================================
// 이번 주 추첨 통계 관련 함수
// ===================================
/* 이번 주 추첨 통계 로드 함수 */
async function loadUpcomingDrawStats() {
try {
console.log('🔄 이번 주 추첨 통계 로드 시작');
const response = await fetch(`api/get_upcoming_draw_stats.php?t=${Date.now()}`);
const data = await response.json();
if (data.success) {
updateUpcomingDrawStatsUI(data);
console.log('✅ 이번 주 추첨 통계 로드 성공');
} else {
displayUpcomingDrawStatsError(data.message);
console.error('❌ 이번 주 추첨 통계 로드 실패:', data.message);
}
} catch (error) {
logger.error('이번 주 추첨 통계 로드 실패', error);
displayUpcomingDrawStatsError('이번 주 추첨 통계를 불러오는데 실패했습니다.');
}
}
/* 추첨 통계용 번호 클래스 반환 함수 */
const upcomingStats = {
getNumberClass: function(num) {
if (num <= 10) return 'upcoming-1-10';
if (num <= 20) return 'upcoming-11-20';
if (num <= 30) return 'upcoming-21-30';
if (num <= 40) return 'upcoming-31-40';
return 'upcoming-41-45';
}
};
/* 이번 주 추첨 통계 UI 업데이트 */
function updateUpcomingDrawStatsUI(data) {
const container = document.getElementById('upcomingDrawStats');
if (!container) {
console.log('upcomingDrawStats 컨테이너를 찾을 수 없음');
return;
}
const weekInfo = data.week_info;
const stats = data.stats;
let html = `
제${weekInfo.upcoming_round}회 추첨을 위한 이번 주 현황
${weekInfo.collection_period}
추첨일: ${weekInfo.draw_date} (토요일) 오후 8시 45분
`;
// 인기 번호 TOP 5 표시 (유니크 클래스 사용)
Object.entries(stats.top_numbers).forEach(([num, count]) => {
html += `
${num}
${count}회
`;
});
html += `
* 이번 주 가장 많이 선택된 번호들
이번 주 비인기 번호 TOP 5
`;
// 비인기 번호 TOP 5 표시 (유니크 클래스 사용)
Object.entries(stats.bottom_numbers).forEach(([num, count]) => {
html += `
${num}
${count}회
`;
});
html += `
* 이번 주 적게 선택된 번호들
`;
// 미선택 번호가 있는 경우 표시
if (stats.unselected_count > 0) {
html += `
아직 선택되지 않은 번호 (${stats.unselected_count}개)
`;
stats.unselected_numbers.slice(0, 10).forEach(num => {
html += `
${num}
`;
});
if (stats.unselected_count > 10) {
html += `외 ${stats.unselected_count - 10}개`;
}
html += `
* 이번 주 아직 한 번도 선택되지 않은 번호들
`;
}
container.innerHTML = html;
}
/* 이번 주 추첨 통계 에러 표시 */
function displayUpcomingDrawStatsError(message) {
const container = document.getElementById('upcomingDrawStats');
if (container) {
container.innerHTML = `
${message}
`;
}
}
/* 주간 당첨 통계 UI 업데이트 */
function updateWeeklyWinningStatsUI(data) {
const container = document.getElementById('winningStats');
if (!container) return;
const stats = data.stats;
const weekInfo = data.week_info;
const winners = data.winners || [];
const checkResult = data.check_result;
let html = '
`;
});
// 더 많은 당첨자가 있는 경우 "더보기" 버튼
const totalWinners = Object.values(stats.ranks).reduce((sum, rank) => sum + rank.count, 0);
if (totalWinners > 5) {
html += `
`;
}
html += '
';
}
// 처리 정보 (개발용)
if (checkResult && checkResult.processing_time) {
html += `
마지막 체크: ${checkResult.total_checked}개 처리
(${checkResult.processing_time}ms)
${checkResult.error_count > 0 ? `, 오류 ${checkResult.error_count}개` : ''}
`;
}
html += '
';
container.innerHTML = html;
}
/* 주간 통계 에러 표시 */
function displayWeeklyStatsError(message) {
const container = document.getElementById('winningStats');
if (container) {
container.innerHTML = `
${message}
`;
}
}
/* 당첨 통계 UI 업데이트 */
function updateWinningStatsUI(stats) {
const container = document.getElementById('winningStats');
if (!container) return;
let html = '
';
// 전체 통계
html += `
${stats.total.totalNumbers.toLocaleString()}
총 생성 번호
${stats.total.totalWinners.toLocaleString()}
총 당첨 번호
${stats.total.winningRate}%
전체 당첨률
${stats.recent.rate}%
최근 7일 당첨률
`;
// 등급별 통계
html += '
등급별 당첨 현황
';
for (let rank = 1; rank <= 5; rank++) {
html += `
${rank}등
${stats.ranks[rank] || 0}명
${stats.ranks[rank] > 0 ? `
` : ''}
`;
}
html += '
';
// 최고 당첨자
if (stats.topWinners && stats.topWinners.length > 0) {
html += '
';
container.innerHTML = html;
}
// ===================================
// 이벤트 핸들러
// ===================================
/* 회차 정보 모달 표시 */
async function showRoundInfo(round) {
const roundInfo = lottoHistory.find(info => info.round === round);
if (!roundInfo) {
logger.error('회차 정보를 찾을 수 없음:', round);
alert('회차 정보를 찾을 수 없습니다.');
return;
}
logger.log('회차 정보 표시:', roundInfo);
const modalHtml = `
제 ${roundInfo.round}회 추첨결과
${roundInfo.drawDate} 추첨
${roundInfo.numbers.map(num => `
${num}
`).join('')}
${roundInfo.bonusNumber}
당첨 정보
• 1등: 6개 번호 일치
• 2등: 5개 번호 + 보너스 번호 일치
• 3등: 5개 번호 일치
• 4등: 4개 번호 일치
• 5등: 3개 번호 일치
`;
const existingModal = document.getElementById('roundInfoModal');
if (existingModal) {
existingModal.remove();
}
document.body.insertAdjacentHTML('beforeend', modalHtml);
const modal = new bootstrap.Modal(document.getElementById('roundInfoModal'));
modal.show();
}
/* 번호 생성 이벤트 핸들러 */
async function generateNumbers() {
if (isGenerating) return;
isGenerating = true;
preview.stop();
ui.displayLoading('lottoNumbers');
console.log('=== 번호 생성 시작 ===');
try {
const numbers = await api.generateNumbers();
console.log('생성된 번호:', numbers);
if (numbers) {
const userInitialInput = document.getElementById('userInitial');
const userInitial = userInitialInput ? userInitialInput.value.trim() : '';
const matchingRound = ui.findMatchingRound(numbers);
ui.displayNumbers(numbers, 'lottoNumbers', userInitial);
// 번호 저장 (강화된 에러 처리)
let saveAttempts = 0;
let saveSuccess = false;
const maxAttempts = 3;
while (saveAttempts < maxAttempts && !saveSuccess) {
saveAttempts++;
console.log(`💾 저장 시도 ${saveAttempts}/${maxAttempts}`);
try {
// 각 시도 사이에 짧은 지연
if (saveAttempts > 1) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
const saveResult = await numberSaver.saveNumber(numbers, userInitial || '익명');
console.log(`저장 시도 ${saveAttempts} 결과:`, saveResult);
if (saveResult && saveResult.success) {
console.log('✅ 저장 성공!');
saveSuccess = true;
// 주간 정보 표시 (당첨 알림 대신)
if (saveResult.week_info) {
displayWeekInfo(saveResult.week_info);
}
// 성공적으로 저장된 경우 통계 업데이트
setTimeout(() => {
stats.updateStatsUI();
loadWinningStats();
if (typeof publicLog !== 'undefined' && publicLog.refresh) {
publicLog.refresh();
}
}, 2000);
} else {
console.warn(`❌ 저장 시도 ${saveAttempts} 실패:`, saveResult?.message || '알 수 없는 오류');
// 마지막 시도가 아니면 계속 시도
if (saveAttempts < maxAttempts) {
console.log('다시 시도합니다...');
continue;
}
}
} catch (error) {
console.error(`❌ 저장 시도 ${saveAttempts} 중 예외 발생:`, error);
// 마지막 시도가 아니면 계속 시도
if (saveAttempts < maxAttempts) {
console.log('예외 발생으로 인한 재시도...');
continue;
}
}
}
// 모든 시도가 실패한 경우 사용자에게 알림
if (!saveSuccess) {
console.error('❌ 모든 저장 시도 실패');
// 사용자에게 실패 알림 표시
const alertHtml = `
저장 실패
번호는 생성되었지만 서버 저장에 실패했습니다.
히스토리에는 저장되었으며, 잠시 후 다시 시도해보세요.
`;
document.body.insertAdjacentHTML('beforeend', alertHtml);
setTimeout(() => {
const alert = document.querySelector('.alert-warning');
if (alert) {
alert.remove();
}
}, 7000);
}
} else {
ui.displayError('lottoNumbers', '번호 생성에 실패했습니다.');
preview.start();
}
} catch (error) {
console.error('❌ 번호 생성 중 예외 발생:', error);
ui.displayError('lottoNumbers', '번호 생성 중 오류가 발생했습니다.');
preview.start();
} finally {
isGenerating = false;
console.log('=== 번호 생성 종료 ===');
}
}
/* 주간 정보 표시 함수 */
function displayWeekInfo(weekInfo) {
if (weekInfo.is_before_draw) {
const alertId = 'alert-' + Date.now(); // 고유 ID 생성
const alertHtml = `
번호 생성 완료!
${weekInfo.message}
이번 주 총 ${weekInfo.total_this_week}개 번호 생성됨
`;
document.body.insertAdjacentHTML('beforeend', alertHtml);
// 3초 후 자동 제거
setTimeout(() => {
const alertElement = document.getElementById(alertId);
if (alertElement) {
// 페이드 아웃 효과
alertElement.style.transition = 'opacity 0.5s ease';
alertElement.style.opacity = '0';
// 페이드 완료 후 DOM에서 제거
setTimeout(() => {
if (alertElement && alertElement.parentNode) {
alertElement.parentNode.removeChild(alertElement);
}
}, 500);
}
}, 3000);
}
}
/* 번호 생성 후 상단 이동 */
async function generateNumbersAndScrollToTop() {
// 상단으로 부드럽게 스크롤
window.scrollTo({
top: 0,
behavior: 'smooth'
});
// 스크롤 완료 후 번호 생성
setTimeout(() => {
generateNumbers();
}, 500);
}
// ===================================
// 페이지 초기화
// ===================================
/* 페이지 초기화 */
async function initializePage() {
console.log('=== 페이지 초기화 시작 ===');
// 저장된 히스토리 로드
const savedHistory = storage.loadHistory();
if (savedHistory && savedHistory.length > 0) {
numberHistory = savedHistory;
ui.updateHistoryUI();
}
// 로또 히스토리 데이터 로드 (수정)
console.log('로또 히스토리 로드 시작...');
try {
await api.loadLottoHistory();
console.log('로또 히스토리 로드 완료. lottoHistory:', lottoHistory);
} catch (error) {
console.error('로또 히스토리 로드 실패:', error);
}
// 현재 당첨번호 정보 로드
loadCurrentLottoInfo();
// 통계 업데이트
stats.updateStatsUI();
// 최신 회차 등급별 당첨 현황 로드
loadLatestRoundWinningStats();
// 당첨 통계 로드
loadWinningStats();
// 이번 주 추첨 통계 로드
loadUpcomingDrawStats();
// 동적 번호 프리뷰 시작
preview.start();
// FAQ 검색 기능 초기화
initFAQSearch();
// 공개 로그 초기 로드 (2초 후)
setTimeout(() => {
if (typeof publicLog !== 'undefined') {
publicLog.refresh();
}
}, 2000);
// 30초마다 자동 새로고침
setInterval(() => {
if (typeof publicLog !== 'undefined') {
publicLog.refresh();
}
}, 30000);
// 30초마다 백그라운드 자동 업데이트
setInterval(() => {
// 사용자가 번호 생성 중이 아닐 때만 업데이트
if (!isGenerating) {
loadCurrentLottoInfo();
loadLatestRoundWinningStats();
loadWinningStats();
loadUpcomingDrawStats();
}
}, 30000); // 30초
}
// ===================================
// 추가 기능
// ===================================
/* FAQ 검색 기능 */
function initFAQSearch() {
const searchInput = document.getElementById('faqSearch');
if (!searchInput) return;
searchInput.addEventListener('input', function(e) {
const query = e.target.value.toLowerCase();
const accordionItems = document.querySelectorAll('.accordion-item');
accordionItems.forEach(item => {
const title = item.querySelector('.accordion-button').textContent.toLowerCase();
const content = item.querySelector('.accordion-body').textContent.toLowerCase();
if (title.includes(query) || content.includes(query)) {
item.style.display = 'block';
} else {
item.style.display = query ? 'none' : 'block';
}
});
});
}
/* 스크롤 관련 기능 */
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
/* 공유 기능 */
function shareApp() {
if (navigator.share) {
navigator.share({
title: '로또당첨번호 조합기',
text: '무료 로또 번호 생성기/추출기로 행운의 번호를 만들어보세요!',
url: window.location.href
}).catch(() => fallbackShare());
} else {
fallbackShare();
}
}
/* 공유 폴백 기능 */
function fallbackShare() {
navigator.clipboard.writeText(window.location.href)
.then(() => alert('URL이 복사되었습니다!'))
.catch(() => alert('URL 복사에 실패했습니다.'));
}
/* 스크롤 이벤트 최적화 */
document.addEventListener('DOMContentLoaded', function() {
const floatingButtons = document.querySelector('.floating-buttons');
let lastScrollY = window.scrollY;
let ticking = false;
if (floatingButtons) {
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
floatingButtons.style.display = window.scrollY > 200 ? 'flex' : 'none';
ticking = false;
});
ticking = true;
}
});
}
});
// ===================================
// 이벤트 리스너 등록
// ===================================
/* 페이지 로드 시 초기화 */
document.addEventListener('DOMContentLoaded', initializePage);
/* window 객체에 함수 노출 */
window.showRoundInfo = showRoundInfo;
window.generateNumbers = generateNumbers;
window.generateNumbersAndScrollToTop = generateNumbersAndScrollToTop;
window.storage = storage;
window.scrollToTop = scrollToTop;
window.shareApp = shareApp;
window.refreshPublicLog = refreshPublicLog;
window.imageExport = imageExport;
window.searchUserNumbers = function() { userSearch.searchNumbers(); };
window.loadWinningStats = loadWinningStats;
window.showWeeklyWinnerDetails = showWeeklyWinnerDetails;
window.showWinnerDetailPopup = showWinnerDetailPopup;
window.loadLatestRoundWinningStats = loadLatestRoundWinningStats;
window.showRoundWinnerDetails = showRoundWinnerDetails;
window.handleRoundFilterClick = handleRoundFilterClick;
window.loadUpcomingDrawStats = loadUpcomingDrawStats;
window.loadCurrentLottoInfo = loadCurrentLottoInfo;
/* 당첨자 상세 보기 함수 */
async function showWinnerDetails(rank = null) {
try {
const url = rank ? `api/get_winner_details.php?rank=${rank}` : 'api/get_winner_details.php';
const response = await fetch(url);
const data = await response.json();
if (data.success) {
displayWinnerDetailsModal(data.winners, rank);
} else {
alert('당첨자 정보를 불러오는데 실패했습니다: ' + data.message);
}
} catch (error) {
console.error('당첨자 상세 정보 로드 실패:', error);
alert('당첨자 정보를 불러오는데 실패했습니다.');
}
}
/* 주간 당첨자 상세 보기 함수 */
async function showWeeklyWinnerDetails(rank = null) {
try {
const url = `api/get_winner_details.php?week=current${rank ? `&rank=${rank}` : ''}`;
const response = await fetch(url);
const data = await response.json();
if (data.success) {
displayWeeklyWinnerDetailsModal(data.winners, rank);
} else {
alert('이번 주 당첨자 정보를 불러오는데 실패했습니다: ' + data.message);
}
} catch (error) {
console.error('주간 당첨자 상세 정보 로드 실패:', error);
alert('이번 주 당첨자 정보를 불러오는데 실패했습니다.');
}
}
/* 주간 당첨자 상세 정보 모달 표시 */
function displayWeeklyWinnerDetailsModal(winners, rank) {
const title = rank ? `이번 주 ${rank}등 당첨자` : '이번 주 전체 당첨자';
// 기존 모달과 동일한 구조이지만 "이번 주" 텍스트 추가
let winnersHtml = '';
if (winners.length === 0) {
winnersHtml = `