MediaWiki:TeamBingo.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
// --- Team Bingo Board with Captains and Smart Polling ---
mw.hook('wikipage.content').add(function () {
const currentUser = mw.config.get('wgUserName'); // logged-in user
const containers = document.querySelectorAll(".teamBingoContainer");
if (!containers.length) return;
const infoBox = document.getElementById("teamBingoInfoBox");
// Set default bingo info immediately on page load
infoBox.innerHTML = `
<div style="text-align: center; font-weight: bold; font-size: 16px; margin-bottom: 8px;">
Team Bingo Challenge
</div>
Welcome to the <strong>Roat Pkz Team Bingo #3</strong> event. Each team has its own bingo board — your goal is to collect the drops or items listed on your team’s board to score points. Each completed tile = 1 point.<br><br>
<strong>Rules:</strong><br>
- Only <strong>team captains</strong> can mark tiles for their team.<br>
- Your board updates <strong>in real time every 30 seconds</strong> for all team members.<br>
- Screenshots of drops/items are required for verification.<br>
- Chests, crates, and boxes do <em>not</em> count.<br><br>
<strong>Event ends:</strong> June 28th, 11:59 PM GMT<br><br>
<strong>Rewards:</strong><br>
- 500 CREDITS (25M+) — 1st place<br>
- 300 CREDITS (15M+) — 2nd place<br>
- 200 CREDITS (10M+) — 3rd place<br><br>
`;
const boardState = {}; // central source of truth for all tiles
let lastRevisionId = null;
// Fetch JSON from Module page
function fetchBoardData(callback) {
$.getJSON(mw.util.wikiScript('api'), {
action: 'query',
titles: 'Module:TeamBingo/data.json',
prop: 'revisions',
rvprop: 'content',
format: 'json',
formatversion: 2
}).done(function(data){
if (!data.query.pages[0].revisions) return;
const content = data.query.pages[0].revisions[0].content;
try {
const json = JSON.parse(content);
Object.assign(boardState, json); // update central state
if(callback) callback(boardState);
} catch(e) {
console.error("Failed to parse JSON from Module:TeamBingo/data.json", e);
}
});
}
// Render board function stays exactly the same
function renderBoard(container, teamKey) {
// ... your full renderBoard function untouched ...
// This includes table creation, hover, click handling, checkmark update, progress bar, etc.
}
// Initial render
fetchBoardData(function(boardData){
containers.forEach(container => {
const teamKey = container.getAttribute("data-team");
renderBoard(container, teamKey);
});
});
// --- SMART POLLING ---
function smartPoll() {
if(document.hidden) return;
// Only get the revision ID to check if board changed
$.getJSON(mw.util.wikiScript('api'), {
action: 'query',
titles: 'Module:TeamBingo/data.json',
prop: 'revisions',
rvprop: 'ids',
format: 'json',
formatversion: 2
}).done(function(data){
const page = data.query.pages[0];
if(!page.revisions) return;
const revId = page.revisions[0].revid;
if(lastRevisionId === null) {
lastRevisionId = revId;
return; // first time, no update
}
if(revId !== lastRevisionId) {
lastRevisionId = revId;
// Only fetch full JSON if revision changed
fetchBoardData(function(newState){
// Update only changed tiles
containers.forEach(container => {
const teamKey = container.getAttribute("data-team");
const cells = container.querySelectorAll("td");
cells.forEach((cell,index) => {
const oldVal = boardState[teamKey][`tile_${index}`];
const newVal = newState[teamKey][`tile_${index}`];
if(oldVal !== newVal) {
boardState[teamKey][`tile_${index}`] = newVal;
const checkmark = cell.querySelector(".bingoCheckmark");
if(checkmark) {
checkmark.style.display = newVal ? "block" : "none";
cell.style.background = newVal ? "rgba(76,175,80,0.5)" : "#313e59";
}
}
});
});
});
}
});
}
// Poll every 5 seconds
setInterval(smartPoll, 5000);
});