<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ระบบวิเคราะห์หวยไทย</title>
<link href="https://fonts.googleapis.com/css2?family=Kanit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Kanit', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
color: #333;
overflow-x: hidden;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
.header {
text-align: center;
color: white;
margin-bottom: 40px;
animation: slideDown 0.8s ease-out;
}
.header h1 {
font-size: 3.5rem;
font-weight: 700;
margin-bottom: 10px;
text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.4);
background: linear-gradient(45deg, #ffffff, #f8f9fa);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header p {
font-size: 1.3rem;
opacity: 0.95;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
}
.dashboard {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 25px;
margin-bottom: 40px;
}
.card {
background: rgba(255, 255, 255, 0.98);
border-radius: 25px;
padding: 30px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(15px);
border: 1px solid rgba(255, 255, 255, 0.3);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
animation: fadeInUp 0.6s ease-out;
position: relative;
overflow: hidden;
}
.card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, #667eea, #764ba2, #f093fb, #f5576c);
background-size: 300% 100%;
animation: gradientShift 3s ease infinite;
}
.card:hover {
transform: translateY(-8px) scale(1.02);
box-shadow: 0 30px 60px rgba(0, 0, 0, 0.2);
}
.card h3 {
color: #2d3748;
font-size: 1.5rem;
margin-bottom: 20px;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.lottery-result {
text-align: center;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border-radius: 20px;
padding: 25px;
margin-bottom: 20px;
position: relative;
overflow: hidden;
}
.lottery-result::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.1), transparent);
transform: rotate(45deg);
animation: shine 3s infinite;
}
.lottery-number {
font-size: 3rem;
font-weight: 700;
letter-spacing: 4px;
text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.3);
position: relative;
z-index: 1;
}
.draw-date {
font-size: 1rem;
opacity: 0.95;
margin-top: 8px;
position: relative;
z-index: 1;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 15px;
margin-top: 20px;
}
.stat-item {
text-align: center;
background: linear-gradient(135deg, #4facfe, #00f2fe);
color: white;
padding: 20px 15px;
border-radius: 15px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.stat-item::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s;
}
.stat-item:hover::before {
left: 100%;
}
.stat-item:hover {
transform: translateY(-3px) scale(1.05);
box-shadow: 0 10px 25px rgba(79, 172, 254, 0.4);
}
.stat-value {
font-size: 2rem;
font-weight: 700;
display: block;
text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
}
.stat-label {
font-size: 0.85rem;
opacity: 0.95;
margin-top: 5px;
font-weight: 500;
}
.chart-container {
margin-top: 20px;
background: #f8f9fa;
border-radius: 15px;
padding: 20px;
position: relative;
}
.chart-canvas {
max-height: 400px;
}
.refresh-btn {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
padding: 15px 30px;
border-radius: 50px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
font-family: 'Kanit', sans-serif;
position: relative;
overflow: hidden;
width: 100%;
}
.refresh-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.6s;
}
.refresh-btn:hover::before {
left: 100%;
}
.refresh-btn:hover {
transform: translateY(-3px);
box-shadow: 0 12px 35px rgba(102, 126, 234, 0.5);
}
.refresh-btn:active {
transform: translateY(-1px);
}
.analysis-section {
margin-top: 40px;
}
.prediction-card {
background: linear-gradient(135deg, #f093fb, #f5576c);
color: white;
border-radius: 25px;
padding: 30px;
text-align: center;
margin-top: 25px;
position: relative;
overflow: hidden;
}
.prediction-card::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
animation: pulse 4s ease-in-out infinite;
}
.prediction-numbers {
display: flex;
justify-content: center;
gap: 15px;
margin: 20px 0;
flex-wrap: wrap;
}
.prediction-number {
background: rgba(255, 255, 255, 0.25);
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 1.4rem;
backdrop-filter: blur(10px);
border: 2px solid rgba(255, 255, 255, 0.3);
transition: all 0.3s ease;
position: relative;
z-index: 1;
}
.prediction-number:hover {
transform: scale(1.1);
background: rgba(255, 255, 255, 0.35);
}
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-top: 3px solid #ffffff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-left: 10px;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
padding: 15px 25px;
border-radius: 15px;
color: white;
font-weight: 500;
z-index: 1000;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
animation: slideIn 0.4s ease;
max-width: 350px;
}
.notification.success {
background: linear-gradient(135deg, #00b894, #00a085);
}
.notification.warning {
background: linear-gradient(135deg, #fdcb6e, #e17055);
}
.notification.error {
background: linear-gradient(135deg, #ff6b6b, #ee5a24);
}
.api-status {
margin: 15px 0;
padding: 12px;
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
backdrop-filter: blur(10px);
}
.status-indicator {
display: flex;
align-items: center;
gap: 8px;
color: white;
font-size: 0.9rem;
}
.status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: #666;
animation: pulse 2s infinite;
}
.status-dot.online {
background: #00b894;
box-shadow: 0 0 10px rgba(0, 184, 148, 0.6);
}
.status-dot.offline {
background: #ff6b6b;
box-shadow: 0 0 10px rgba(255, 107, 107, 0.6);
}
.status-dot.testing {
background: #fdcb6e;
box-shadow: 0 0 10px rgba(253, 203, 110, 0.6);
}
.api-sources {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 15px;
backdrop-filter: blur(10px);
}
.sources-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
margin-top: 10px;
}
.source-item {
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 10px;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
border: 2px solid transparent;
font-size: 0.85rem;
}
.source-item:hover {
background: rgba(255, 255, 255, 0.15);
transform: translateY(-2px);
}
.source-item.active {
border-color: #00b894;
background: rgba(0, 184, 148, 0.2);
}
.source-item.disabled {
opacity: 0.5;
cursor: not-allowed;
background: rgba(255, 107, 107, 0.1);
}
.source-item.disabled:hover {
transform: none;
background: rgba(255, 107, 107, 0.1);
}
.source-name {
font-weight: 600;
color: white;
margin-bottom: 5px;
}
.source-status {
font-size: 0.75rem;
opacity: 0.8;
color: white;
}
.source-dot {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
margin-right: 5px;
}
.source-dot.online {
background: #00b894;
}
.source-dot.offline {
background: #ff6b6b;
}
.source-dot.testing {
background: #fdcb6e;
}
.source-dot.unknown {
background: #666;
}
@keyframes gradientShift {
0%,
100% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
}
@keyframes shine {
0% {
transform: translateX(-100%) translateY(-100%) rotate(45deg);
}
100% {
transform: translateX(100%) translateY(100%) rotate(45deg);
}
}
@keyframes pulse {
0%,
100% {
transform: scale(1) rotate(0deg);
opacity: 0.5;
}
50% {
transform: scale(1.1) rotate(180deg);
opacity: 0.8;
}
}
@keyframes slideDown {
from {
transform: translateY(-50px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes fadeInUp {
from {
transform: translateY(30px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOut {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
@media (max-width: 768px) {
.header h1 {
font-size: 2.5rem;
}
.container {
padding: 15px;
}
.dashboard {
grid-template-columns: 1fr;
gap: 20px;
}
.lottery-number {
font-size: 2.2rem;
}
.prediction-numbers {
gap: 10px;
}
.prediction-number {
width: 50px;
height: 50px;
font-size: 1.2rem;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🎯 ระบบวิเคราะห์หวยไทย</h1>
<p>วิเคราะห์สถิติและความน่าจะเป็นของผลสลากกินแบ่งรัฐบาล</p>
</div>
<div class="dashboard">
<div class="card">
<h3>🏆 ผลสลากล่าสุด</h3>
<div class="lottery-result">
<div class="lottery-number" id="latestResult">123456</div>
<div class="draw-date" id="drawDate">งวดวันที่ 1 กรกฎาคม 2567</div>
</div>
<div class="api-status" id="apiStatus">
<div class="status-indicator">
<span class="status-dot" id="statusDot"></span>
<span class="status-text" id="statusText">กำลังตรวจสอบ API...</span>
</div>
</div>
<button class="refresh-btn" onclick="fetchLatestResult()" id="refreshBtn">
🔄 อัปเดตผล
</button>
</div>
<div class="card">
<h3>📊 สถิติรวม</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-value" id="totalDraws">156</span>
<div class="stat-label">งวดทั้งหมด</div>
</div>
<div class="stat-item">
<span class="stat-value" id="avgSum">284</span>
<div class="stat-label">ผลรวมเฉลี่ย</div>
</div>
<div class="stat-item">
<span class="stat-value" id="evenOddRatio">52%</span>
<div class="stat-label">เลขคู่</div>
</div>
<div class="stat-item">
<span class="stat-value" id="hotNumber">7</span>
<div class="stat-label">เลขฮอต</div>
</div>
</div>
</div>
<div class="card">
<h3>🔥 ความถี่ตัวเลข (หลักหน่วย)</h3>
<div class="chart-container">
<canvas id="frequencyChart" class="chart-canvas"></canvas>
</div>
</div>
<div class="card">
<h3>📈 แนวโน้มผลรวมรางวัล</h3>
<div class="chart-container">
<canvas id="trendChart" class="chart-canvas"></canvas>
</div>
</div>
<div class="card">
<h3>🎲 การวิเคราะห์รูปแบบ</h3>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-value" id="consecutiveCount">23</span>
<div class="stat-label">เลขต่อเนื่อง</div>
</div>
<div class="stat-item">
<span class="stat-value" id="repeatCount">45</span>
<div class="stat-label">เลขซ้ำ</div>
</div>
<div class="stat-item">
<span class="stat-value" id="mirrorCount">12</span>
<div class="stat-label">เลขกลับ</div>
</div>
<div class="stat-item">
<span class="stat-value" id="sumPattern">312</span>
<div class="stat-label">ผลรวมมาก</div>
</div>
</div>
</div>
</div>
<div class="analysis-section">
<div class="card">
<h3>🔮 การพยากรณ์แนวโน้ม</h3>
<p style="margin-bottom: 15px; color: #666;">จากการวิเคราะห์ข้อมูลย้อนหลัง แนวโน้มเลขที่อาจออกในงวดหน้า:</p>
<div class="prediction-card">
<h4>🎯 เลขเด่นแนะนำ</h4>
<div class="prediction-numbers" id="predictionNumbers">
<!-- จะถูกสร้างด้วย JavaScript -->
</div>
<p style="font-size: 0.9rem; opacity: 0.8; margin-top: 15px;">
* คำแนะนำนี้อ้างอิงจากสถิติเท่านั้น ไม่ใช่การรับประกันผล
</p>
</div>
</div>
</div>
</div>
<script>
// ฟังก์ชันแสดง notification
function showNotification(message, type = 'info') {
// ลบการแจ้งเตือนเก่า
const existingNotifications = document.querySelectorAll('.notification');
existingNotifications.forEach(n => n.remove());
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.animation = 'slideOut 0.4s ease';
setTimeout(() => notification.remove(), 400);
}, 3000);
}
// โหลดข้อมูลหวยย้อนหลังจาก cache JSON โดยตรง
let lotteryHistory = [];
let frequencyChart = null;
let trendChart = null;
// ฟังก์ชันเช็คว่าวันนี้ตรงกับวันหวยออกหรือ ±1 วันไหม
function isLotteryDayOrNearby(date = new Date()) {
const d = date.getDate();
return [1, 2, 15, 16, 17, 31].includes(d);
}
// ฟังก์ชันเช็คว่า cache เก่าเกินไปไหม (timestamp เกิน 36 ชม. หรือวันล่าสุดใน cache ไม่ตรงวันหวยออก)
function isCacheStale(cacheData) {
if (!cacheData || !cacheData.timestamp || !cacheData.data || !cacheData.data.length) return true;
const now = Date.now();
const cacheTime = cacheData.timestamp * 1000;
if (now - cacheTime > 36 * 60 * 60 * 1000) return true; // เกิน 36 ชม.
// ตรวจสอบว่างวดล่าสุดใน cache ตรงกับวันหวยออกหรือไม่
const latest = cacheData.data[0];
if (!latest || !latest.date) return true;
const latestDate = new Date(latest.date);
const today = new Date();
// ถ้าวันนี้ตรงกับวันหวยออกหรือ ±1 วัน แต่ cache ไม่ใช่งวดล่าสุด
if (isLotteryDayOrNearby(today)) {
// ถ้า latestDate ไม่ใช่วันนี้หรือเมื่อวานหรือพรุ่งนี้
const diff = Math.abs(today - latestDate) / (1000 * 60 * 60 * 24);
if (diff > 1.5) return true;
}
return false;
}
// ฟังก์ชันโหลด cache พร้อม auto update ถ้าจำเป็น
async function loadLotteryCacheWithAutoUpdate() {
let cacheData = null;
let needUpdate = false;
try {
const response = await fetch('api/lottery_cache.json', {cache: 'no-store'});
if (!response.ok) throw new Error('ไม่พบ cache');
cacheData = await response.json();
if (isLotteryDayOrNearby() && isCacheStale(cacheData)) {
needUpdate = true;
}
} catch (e) {
needUpdate = true;
}
if (needUpdate) {
showNotification('⏳ กำลังอัปเดตข้อมูลหวยล่าสุด...', 'info');
try {
await fetch('api/update_cache.php', {method: 'POST', cache: 'no-store'});
// รอ 1 วิ ให้ backend สร้าง cache
await new Promise(res => setTimeout(res, 1000));
const response = await fetch('api/lottery_cache.json', {cache: 'no-store'});
if (!response.ok) throw new Error('อัปเดต cache ไม่สำเร็จ');
cacheData = await response.json();
showNotification('✅ อัปเดต cache สำเร็จ!', 'success');
} catch (e) {
showNotification('❌ อัปเดต cache ไม่สำเร็จ', 'error');
cacheData = null;
}
}
// อัปเดต lotteryHistory และ hotNumbers
if (cacheData && cacheData.data && cacheData.data.length > 0) {
lotteryHistory = cacheData.data.map(record => ({
number: record.prize1,
date: record.date,
sum: record.prize1.split('').reduce((a, b) => a + parseInt(b), 0),
timestamp: new Date(record.date).getTime()
}));
window.hotNumbers = generateHotNumbers(lotteryHistory);
} else {
lotteryHistory = [];
window.hotNumbers = [];
}
}
// ฟังก์ชัน generate เลขเด่น 3 หลัก (hotNumber) จากข้อมูลดิบ
function generateHotNumbers(history) {
const digitFreq = {};
for (let i = 0; i <= 9; i++) digitFreq[i] = 0;
history.forEach(item => {
const digits = item.number.split('');
digits.forEach(digit => {digitFreq[digit]++;});
});
// เรียงจากมากไปน้อย เอา 3 ตัวแรก
return Object.entries(digitFreq)
.sort((a, b) => b[1] - a[1])
.slice(0, 3)
.map(entry => entry[0]);
}
// อัปเดตผลสลากล่าสุดและเลขเด่น (3 ตัว)
function updateLatestResult() {
if (lotteryHistory.length === 0) return;
const latest = lotteryHistory[0];
document.getElementById('latestResult').textContent = latest.number;
document.getElementById('drawDate').textContent = `งวดวันที่ ${formatThaiDate(latest.date)}`;
// แสดงเลขเด่น (3 ตัวเท่านั้น)
const predDiv = document.getElementById('predictionNumbers');
predDiv.innerHTML = '';
if (window.hotNumbers && window.hotNumbers.length > 0) {
window.hotNumbers.slice(0, 3).forEach(num => {
const el = document.createElement('div');
el.className = 'prediction-number';
el.textContent = num;
predDiv.appendChild(el);
});
} else {
predDiv.innerHTML = '<div class="prediction-number">-</div>';
}
}
// อัปเดตสถิติ (เหมือนเดิม)
async function updateStatistics() {
if (lotteryHistory.length === 0) return;
const totalDraws = lotteryHistory.length;
const avgSum = Math.round(lotteryHistory.reduce((sum, item) => sum + item.sum, 0) / totalDraws);
let evenCount = 0;
lotteryHistory.forEach(item => {
const lastDigit = parseInt(item.number.slice(-1));
if (lastDigit % 2 === 0) evenCount++;
});
const evenRatio = Math.round((evenCount / totalDraws) * 100);
const digitFreq = {};
lotteryHistory.forEach(item => {
const digits = item.number.split('');
digits.forEach(digit => {
digitFreq[digit] = (digitFreq[digit] || 0) + 1;
});
});
const hotNumber = Object.keys(digitFreq).reduce((a, b) => digitFreq[a] > digitFreq[b] ? a : b);
document.getElementById('totalDraws').textContent = totalDraws;
document.getElementById('avgSum').textContent = avgSum;
document.getElementById('evenOddRatio').textContent = evenRatio + '%';
document.getElementById('hotNumber').textContent = hotNumber;
const consecutiveCount = analyzeConsecutiveNumbers();
const repeatCount = analyzeRepeatingDigits();
const mirrorCount = analyzeMirrorNumbers();
const sumPattern = analyzeHighSumPatterns();
document.getElementById('consecutiveCount').textContent = consecutiveCount;
document.getElementById('repeatCount').textContent = repeatCount;
document.getElementById('mirrorCount').textContent = mirrorCount;
document.getElementById('sumPattern').textContent = sumPattern;
}
// วิเคราะห์เลขต่อเนื่อง
function analyzeConsecutiveNumbers() {
let count = 0;
lotteryHistory.forEach(item => {
const digits = item.number.split('').map(Number);
for (let i = 0; i < digits.length - 1; i++) {
if (Math.abs(digits[i] - digits[i + 1]) === 1) {
count++;
break;
}
}
});
return count;
}
// วิเคราะห์เลขซ้ำ
function analyzeRepeatingDigits() {
let count = 0;
lotteryHistory.forEach(item => {
const digits = item.number.split('');
const uniqueDigits = new Set(digits);
if (uniqueDigits.size < digits.length) {
count++;
}
});
return count;
}
// วิเคราะห์เลขกลับ
function analyzeMirrorNumbers() {
let count = 0;
lotteryHistory.forEach(item => {
const number = item.number;
const reversed = number.split('').reverse().join('');
if (number.substring(0, 3) === reversed.substring(0, 3)) {
count++;
}
});
return count;
}
// วิเคราะห์ผลรวมสูง
function analyzeHighSumPatterns() {
const highSumCount = lotteryHistory.filter(item => item.sum > 25).length;
return highSumCount;
}
// อัปเดตกราฟทั้งหมด
function updateCharts() {
updateFrequencyChart();
updateTrendChart();
}
// อัปเดตกราฟความถี่
function updateFrequencyChart() {
const ctx = document.getElementById('frequencyChart').getContext('2d');
// คำนวณความถี่ของแต่ละตัวเลข (หลักหน่วย)
const frequency = {};
for (let i = 0; i <= 9; i++) {
frequency[i] = 0;
}
lotteryHistory.forEach(item => {
const lastDigit = parseInt(item.number.slice(-1));
frequency[lastDigit]++;
});
const labels = Object.keys(frequency);
const data = Object.values(frequency);
if (frequencyChart) {
frequencyChart.destroy();
}
frequencyChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'ความถี่',
data: data,
backgroundColor: [
'rgba(102, 126, 234, 0.8)',
'rgba(118, 75, 162, 0.8)',
'rgba(240, 147, 251, 0.8)',
'rgba(245, 87, 108, 0.8)',
'rgba(79, 172, 254, 0.8)',
'rgba(0, 242, 254, 0.8)',
'rgba(253, 203, 110, 0.8)',
'rgba(225, 112, 85, 0.8)',
'rgba(0, 184, 148, 0.8)',
'rgba(255, 107, 107, 0.8)'
],
borderColor: [
'rgba(102, 126, 234, 1)',
'rgba(118, 75, 162, 1)',
'rgba(240, 147, 251, 1)',
'rgba(245, 87, 108, 1)',
'rgba(79, 172, 254, 1)',
'rgba(0, 242, 254, 1)',
'rgba(253, 203, 110, 1)',
'rgba(225, 112, 85, 1)',
'rgba(0, 184, 148, 1)',
'rgba(255, 107, 107, 1)'
],
borderWidth: 2,
borderRadius: 8,
borderSkipped: false,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: '#fff',
bodyColor: '#fff',
borderColor: '#667eea',
borderWidth: 1,
cornerRadius: 8,
displayColors: false
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.1)',
drawBorder: false
},
ticks: {
color: '#666',
font: {
family: 'Kanit',
size: 12
}
}
},
x: {
grid: {
display: false
},
ticks: {
color: '#666',
font: {
family: 'Kanit',
size: 12,
weight: 'bold'
}
}
}
},
animation: {
duration: 1000,
easing: 'easeOutQuart'
}
}
});
}
// อัปเดตกราฟแนวโน้ม
function updateTrendChart() {
const ctx = document.getElementById('trendChart').getContext('2d');
const labels = lotteryHistory.slice(0, 15).reverse().map(item => {
const date = new Date(item.date);
return date.toLocaleDateString('th-TH', {month: 'short', day: 'numeric'});
});
const sumData = lotteryHistory.slice(0, 15).reverse().map(item => item.sum);
if (trendChart) {
trendChart.destroy();
}
trendChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'ผลรวมรางวัล',
data: sumData,
borderColor: 'rgba(102, 126, 234, 1)',
backgroundColor: 'rgba(102, 126, 234, 0.1)',
borderWidth: 3,
fill: true,
tension: 0.4,
pointBackgroundColor: '#667eea',
pointBorderColor: '#fff',
pointBorderWidth: 2,
pointRadius: 6,
pointHoverRadius: 8,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: '#fff',
bodyColor: '#fff',
borderColor: '#667eea',
borderWidth: 1,
cornerRadius: 8,
displayColors: false
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.1)',
drawBorder: false
},
ticks: {
color: '#666',
font: {
family: 'Kanit',
size: 12
}
}
},
x: {
grid: {
display: false
},
ticks: {
color: '#666',
font: {
family: 'Kanit',
size: 11
}
}
}
},
animation: {
duration: 1000,
easing: 'easeOutQuart'
}
}
});
}
// เริ่มต้นเมื่อโหลดหน้า
document.addEventListener('DOMContentLoaded', async function() {
await loadLotteryCacheWithAutoUpdate();
updateLatestResult();
await updateStatistics();
updateCharts();
showNotification('✅ ระบบพร้อมใช้งาน!', 'success');
});
// ปุ่มอัปเดตผล (โหลด cache ใหม่)
document.getElementById('refreshBtn').onclick = async function() {
await loadLotteryCacheWithAutoUpdate();
updateLatestResult();
await updateStatistics();
updateCharts();
showNotification('🔄 โหลดข้อมูลหวยล่าสุดจาก cache สำเร็จ!', 'success');
}
// เพิ่มเอฟเฟกต์ให้กับการ์ด
document.querySelectorAll('.card').forEach((card, index) => {
card.style.animationDelay = `${index * 0.1}s`;
});
// เพิ่ม CSS animations
const style = document.createElement('style');
style.textContent = `
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
`;
document.head.appendChild(style);
// เพิ่มฟังก์ชันแปลงวันที่ไทยจาก date (ISO)
function formatThaiDate(dateStr) {
const months = [
'', 'ม.ค.', 'ก.พ.', 'มี.ค.', 'เม.ย.', 'พ.ค.', 'มิ.ย.',
'ก.ค.', 'ส.ค.', 'ก.ย.', 'ต.ค.', 'พ.ย.', 'ธ.ค.'
];
const [year, month, day] = dateStr.split('-');
const thaiYear = (parseInt(year, 10) + 543).toString().slice(-2);
return `${parseInt(day, 10)} ${months[parseInt(month, 10)]} ${thaiYear}`;
}
</script>
</body>
</html>