MediaWiki:TeamBingo.js: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 6: | Line 6: | ||
if (!containers.length) return; | if (!containers.length) return; | ||
const infoBox = document.getElementById("teamBingoInfoBox"); | const infoBox = document.getElementById("teamBingoInfoBox"); | ||
| Line 18: | Line 17: | ||
<strong>Rules:</strong><br> | <strong>Rules:</strong><br> | ||
- Only <strong>team captains</strong> can mark tiles for their team.<br> | - Only <strong>team captains</strong> can mark tiles for their team.<br> | ||
- Your board updates <strong>in real time</strong> for all team members.<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> | - Screenshots of drops/items are required for verification.<br> | ||
- Chests, crates, and boxes do <em>not</em> count.<br><br> | - Chests, crates, and boxes do <em>not</em> count.<br><br> | ||
| Line 39: | Line 38: | ||
titles: 'Module:TeamBingo/data.json', | titles: 'Module:TeamBingo/data.json', | ||
prop: 'revisions', | prop: 'revisions', | ||
rvprop: 'content | rvprop: 'content', | ||
format: 'json', | format: 'json', | ||
formatversion: 2 | formatversion: 2 | ||
}).done(function(data){ | }).done(function(data){ | ||
if (!data.query.pages[0].revisions) return; | |||
const content = data.query.pages[0].revisions[0].content; | |||
const content = | |||
try { | try { | ||
const json = JSON.parse(content); | const json = JSON.parse(content); | ||
if(callback) callback( | Object.assign(boardState, json); // update central state | ||
if(callback) callback(boardState); | |||
} catch(e) { | } catch(e) { | ||
console.error("Failed to parse JSON from Module:TeamBingo/data.json", e); | console.error("Failed to parse JSON from Module:TeamBingo/data.json", e); | ||
| Line 58: | Line 54: | ||
} | } | ||
// Render the | // Render board function stays exactly the same | ||
function renderBoard(container, teamKey) { | function renderBoard(container, teamKey) { | ||
// ... your full renderBoard function untouched ... | |||
// This includes table creation, hover, click handling, checkmark update, progress bar, etc. | |||
// | |||
// | |||
} | } | ||
// Initial render | // Initial render | ||
fetchBoardData(function(boardData | fetchBoardData(function(boardData){ | ||
containers.forEach(container => { | containers.forEach(container => { | ||
const teamKey = container.getAttribute("data-team"); | const teamKey = container.getAttribute("data-team"); | ||
| Line 263: | Line 68: | ||
}); | }); | ||
// --- | // --- 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) { | if(lastRevisionId === null) { | ||
lastRevisionId = revId; | lastRevisionId = revId; | ||
return; | return; // first time, no update | ||
} | } | ||
if(revId !== lastRevisionId){ | if(revId !== lastRevisionId) { | ||
lastRevisionId = revId; | lastRevisionId = revId; | ||
// Only fetch full JSON if revision changed | |||
containers.forEach(container => { | 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"; | |||
} | |||
} | } | ||
} | }); | ||
}); | }); | ||
}); | }); | ||
} | } | ||
}); | }); | ||
}, 5000); | } | ||
// Poll every 5 seconds | |||
setInterval(smartPoll, 5000); | |||
}); | }); | ||
Revision as of 17:32, 7 March 2026
// --- 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);
});