292 lines
9.3 KiB
JavaScript
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();
|