// VIP auto-cycling deal display.
// A new discount tier "unlocks" every 48 hours, computed automatically
// from the current time -- runs forever, for a month or a year, with no
// calendar to maintain. Uses the same HTML block as before, so if you
// already set up vip-daily-drop.html, no changes needed there. This
// script replaces vip-daily-drop.js.
//
// SETUP IN CHECKFRONT: create these three as standing discount codes,
// ONCE, no date restriction needed. Being visible only on your gated
// VIP page is the actual access control here, same as everything else
// we discussed -- not a Checkfront date rule.
// VRGH-A7K2 - 30% off
// VRGH-B4M9 - 40% off
// VRGH-C8XQ - 50% off
//
// HOW IT PICKS: time is divided into 48-hour blocks since the Unix
// epoch. Which of the three codes shows is worked out from that block
// number using a simple repeatable formula -- not truly random, but it
// looks varied, and everyone visiting during the same 48-hour window
// sees the same tier, which is what makes the Checkfront code actually
// valid for them.
(function () {
'use strict';
var BOOKING_BASE_URL = 'https://vrgamehouse.checkfront.com/reserve/';
var CYCLE_HOURS = 48;
var CYCLE_MS = CYCLE_HOURS * 60 * 60 * 1000;
var TIERS = [
{ code: 'VRGH-A7K2', discount: '30% off' },
{ code: 'VRGH-B4M9', discount: '40% off' },
{ code: 'VRGH-C8XQ', discount: '50% off' }
];
function pad(n) { return String(n).padStart(2, '0'); }
function currentCycleIndex() {
return Math.floor(Date.now() / CYCLE_MS);
}
// Deterministic, not cryptographic -- only needs to look varied and
// land on the same tier for everyone during the same 48-hour window.
function pickTierForCycle(cycleIndex) {
var x = Math.sin(cycleIndex * 12.9898) * 43758.5453;
var frac = x - Math.floor(x);
var index = Math.floor(frac * TIERS.length);
return TIERS[index];
}
function msUntilNextCycle(cycleIndex) {
var cycleEnd = (cycleIndex + 1) * CYCLE_MS;
return cycleEnd - Date.now();
}
function formatCountdown(ms) {
if (ms < 0) ms = 0;
var totalSeconds = Math.floor(ms / 1000);
var hours = Math.floor(totalSeconds / 3600);
var minutes = Math.floor((totalSeconds % 3600) / 60);
var seconds = totalSeconds % 60;
return pad(hours) + ':' + pad(minutes) + ':' + pad(seconds);
}
var lastCycleIndex = null;
function tick() {
var cycleIndex = currentCycleIndex();
if (cycleIndex !== lastCycleIndex) {
lastCycleIndex = cycleIndex;
var tier = pickTierForCycle(cycleIndex);
var codeEl = document.querySelector('[data-vip-code]');
var discountEl = document.querySelector('[data-vip-discount]');
var statusEl = document.querySelector('[data-vip-status]');
var bookLinkEl = document.querySelector('[data-vip-book-link]');
if (codeEl) codeEl.textContent = tier.code;
if (discountEl) discountEl.textContent = tier.discount;
if (statusEl) statusEl.textContent = 'This deal refreshes automatically';
if (bookLinkEl) {
bookLinkEl.href = BOOKING_BASE_URL + '?discount=' + encodeURIComponent(tier.code);
}
}
var timerEl = document.querySelector('[data-vip-timer]');
if (timerEl) timerEl.textContent = formatCountdown(msUntilNextCycle(cycleIndex));
}
tick();
setInterval(tick, 1000);
})();