2026-05-15 10:23:06 +08:00

292 lines
9.3 KiB
JavaScript

const assetRoot = '../assets/external/yumi-static/other/';
const img = (name) => `${assetRoot}${name}`;
const modeData = {
classic: {
background: 'lucky_box_bg_new.png',
prices: [500, 5000, 25000],
drawAmount: 500,
board: 'grid',
prizes: [
['Coral Crown', 99, 'lucky_box_reward.png'],
['Aurora Wing', 500, 'christmasCheckIn_lottery_go.png'],
['Moon Card', 520, 'lucky_box_select.png'],
['Snow Pet', 777, 'christmasCheckIn_lottery_select.png'],
['Love Banner', 1314, 'lucky_box_title_top.png'],
['Emerald Ring', 1777, 'lucky_box_reward_bg.png'],
['Royal Chest', 3999, 'lucky_box_go.png'],
['Crystal Castle', 199999, 'lucky_box_bg_new.png']
]
},
luxury: {
background: 'lucky_box_tow_bg_new.png',
prices: [2000, 20000, 100000],
drawAmount: 2000,
board: 'wheel',
prizes: [
['Pink Meteor', 2000, 'lucky_box_tow_reward.png'],
['Cupid Wand', 2999, 'lucky_box_tow_pointer.png'],
['Love Ring', 5200, 'lucky_box_tow_reward_yuan.png'],
['Lucky Palace', 6666, 'lucky_box_tow_reward_bg.png'],
['Starlight', 10000, 'lucky_box_tow_reward_desc.png'],
['Rose Horse', 15000, 'lucky_box_tow_reward_top.png'],
['Neon Gift', 50000, 'lucky_box_tow_reward_bottom.png'],
['Galaxy Badge', 299999, 'lucky_box_tow_bg_new.png']
]
},
advanced: {
background: 'lucky_box_three_bg_new.png',
prices: [10000, 100000, 500000],
drawAmount: 10000,
board: 'grid',
prizes: [
['Cyber Cat', 2000, 'lucky_box_three_notice.png'],
['Golden Ride', 4500, 'lucky_box_three_gold.png'],
['Black Rose', 6000, 'lucky_box_three_reward_bg.png'],
['Holy Trophy', 10000, 'lucky_box_three_select.png'],
['Silver Cup', 20000, 'lucky_box_three_history.png'],
['Royal Cake', 50000, 'lucky_box_three_go.png'],
['Night Throne', 100000, 'lucky_box_three_rule.png'],
['Ice Castle', 200000, 'lucky_box_three_unbtn.png'],
['Gold Palace', 300000, 'lucky_box_three_unselect.png'],
['Star Couple', 400000, 'lucky_box_three_default.png'],
['Dragon Ride', 500000, 'lucky_box_three_bg_new.png'],
['Blue Flame', 1000000, 'lucky_box_three_btn.png']
]
}
};
const state = {
mode: 'classic',
activeButton: 0,
activeIndex: null,
spinning: false,
rotateDeg: 0,
balance: 230610000,
history: []
};
const winners = [
['ZAYAN', 'Cyber Cat'],
['Looma', 'Love Ring'],
['Rima', 'Crystal Castle'],
['M7MD', 'Golden Ride'],
['Yara', 'Pink Meteor']
];
const page = document.querySelector('#page');
const stage = document.querySelector('#stage');
const buyRow = document.querySelector('#buyRow');
const balanceTop = document.querySelector('#balanceTop');
const balanceBottom = document.querySelector('#balanceBottom');
const tickerTrack = document.querySelector('#tickerTrack');
const rewardDialog = document.querySelector('#rewardDialog');
const rewardList = document.querySelector('#rewardList');
const rewardText = document.querySelector('#rewardText');
const historyDialog = document.querySelector('#historyDialog');
const historyList = document.querySelector('#historyList');
function money(value) {
return Number(value).toLocaleString('en-US');
}
function prizeObjects() {
return modeData[state.mode].prizes.map(([name, value, cover]) => ({
name,
value,
coverUrl: img(cover)
}));
}
function setMode(mode) {
state.mode = mode;
state.activeButton = 0;
state.activeIndex = null;
render();
}
function render() {
const mode = modeData[state.mode];
page.className = `wheel-page mode-${state.mode}`;
page.style.backgroundImage = `url("${img(mode.background)}")`;
balanceTop.textContent = money(state.balance);
balanceBottom.textContent = money(state.balance);
document.querySelectorAll('.tabs button').forEach((button) => {
button.classList.toggle('active', button.dataset.mode === state.mode);
});
tickerTrack.innerHTML = winners.concat(winners).map(([name, reward]) => (
`<span>Congratulations to ${name} for receiving the ${reward} award</span>`
)).join('');
renderStage();
renderBuyRow();
}
function renderStage() {
const mode = modeData[state.mode];
if (mode.board === 'wheel') {
renderWheel();
return;
}
const prizes = prizeObjects();
const cells = [
prizeCard(prizes[0], 0),
prizeCard(prizes[1], 1),
prizeCard(prizes[2], 2),
prizeCard(prizes[3], 3),
`<button class="go-button" type="button" id="goButton">GO</button>`,
prizeCard(prizes[4], 4),
prizeCard(prizes[5], 5),
prizeCard(prizes[6], 6),
prizeCard(prizes[7], 7)
];
stage.innerHTML = `<div class="grid-board">${cells.join('')}</div>`;
document.querySelector('#goButton').addEventListener('click', startLottery);
}
function renderWheel() {
const prizes = prizeObjects();
const itemMarkup = prizes.map((prize, index) => {
const angle = `${index * (360 / prizes.length)}deg`;
return `<div class="wheel-item" style="--angle:${angle}">
<img src="${prize.coverUrl}" alt="">
<strong>${prize.value}</strong>
</div>`;
}).join('');
stage.innerHTML = `<div class="wheel-wrap">
<div class="wheel-disc" id="wheelDisc" style="transform:rotate(${state.rotateDeg}deg)">${itemMarkup}</div>
<img class="pointer" src="${img('lucky_box_tow_pointer.png')}" alt="">
<button class="wheel-go" id="goButton" type="button">GO</button>
</div>`;
document.querySelector('#goButton').addEventListener('click', startLottery);
}
function prizeCard(prize, index) {
return `<div class="prize-card ${state.activeIndex === index ? 'active' : ''}">
<img src="${prize.coverUrl}" alt="">
<strong>${prize.name}</strong>
<span class="price"><span class="coin-dot"></span>${money(prize.value)}</span>
</div>`;
}
function renderBuyRow() {
buyRow.innerHTML = modeData[state.mode].prices.map((price, index) => (
`<button type="button" data-index="${index}" class="${index === state.activeButton ? 'active' : ''}">
<div>${index === 0 ? '1 Time' : index === 1 ? '10 Time' : '50 Time'}</div>
<div>${money(price)}</div>
</button>`
)).join('');
buyRow.querySelectorAll('button').forEach((button) => {
button.addEventListener('click', () => {
state.activeButton = Number(button.dataset.index);
renderBuyRow();
});
});
}
function startLottery() {
if (state.spinning) return;
const mode = modeData[state.mode];
const cost = mode.prices[state.activeButton];
if (state.balance < cost) return;
state.balance -= cost;
state.spinning = true;
const prizes = prizeObjects();
const target = Math.floor(Math.random() * prizes.length);
if (mode.board === 'wheel') {
state.rotateDeg += 1440 + (360 - target * (360 / prizes.length));
document.querySelector('#wheelDisc').style.transform = `rotate(${state.rotateDeg}deg)`;
setTimeout(() => finishLottery(target), 2300);
renderBuyRow();
balanceTop.textContent = money(state.balance);
balanceBottom.textContent = money(state.balance);
return;
}
let tick = 0;
const timer = setInterval(() => {
state.activeIndex = tick % prizes.length;
renderStage();
tick += 1;
if (tick > 22 && state.activeIndex === target) {
clearInterval(timer);
finishLottery(target);
}
}, tick < 12 ? 70 : 120);
}
function finishLottery(targetIndex) {
const prize = prizeObjects()[targetIndex];
state.spinning = false;
state.activeIndex = targetIndex;
const count = state.activeButton === 0 ? 1 : state.activeButton === 1 ? 10 : 50;
const record = {
time: new Date(),
drawTimes: count,
rewards: [{ ...prize, count: 1 }],
rewardValue: prize.value
};
state.history.unshift(record);
showReward(record);
render();
}
function showReward(record) {
rewardList.innerHTML = record.rewards.map((item) => (
`<div class="reward-row">
<img src="${item.coverUrl}" alt="">
<strong>${item.name}</strong>
<span>x${item.count}</span>
</div>`
)).join('');
rewardText.textContent = `Congratulations on receiving: A precious gift worth ${money(record.rewardValue)} gold coins. Already put in the backpack.`;
rewardDialog.showModal();
}
function renderHistory() {
const records = state.history.length ? state.history : seedHistory();
historyList.innerHTML = records.map((record) => {
const first = record.rewards[0];
return `<div class="history-row">
<img src="${first.coverUrl}" alt="">
<div>
<strong>${first.name}</strong>
<div>${record.time.toLocaleString()}</div>
</div>
<span>x${record.drawTimes}</span>
</div>`;
}).join('');
}
function seedHistory() {
const prizes = prizeObjects();
return [0, 2, 5].map((index, offset) => ({
time: new Date(Date.now() - (offset + 1) * 260000),
drawTimes: [1, 10, 50][offset],
rewards: [{ ...prizes[index], count: offset + 1 }],
rewardValue: prizes[index].value
}));
}
document.querySelectorAll('.tabs button').forEach((button) => {
button.addEventListener('click', () => setMode(button.dataset.mode));
});
document.querySelector('#historyBtn').addEventListener('click', () => {
renderHistory();
historyDialog.showModal();
});
document.querySelector('#closeHistory').addEventListener('click', () => historyDialog.close());
document.querySelector('#closeReward').addEventListener('click', () => rewardDialog.close());
document.querySelector('#drawAgain').addEventListener('click', () => {
rewardDialog.close();
startLottery();
});
render();