|
1229 | 1229 |
|
1230 | 1230 | // ── Activity Feed ──────────────────────────────────────────── |
1231 | 1231 |
|
1232 | | -function updateActivity(data) { |
| 1232 | +// ── Activity feed: bets + match results ──────────────────── |
| 1233 | + |
| 1234 | +let activityItems = []; // { text, type, time } |
| 1235 | +let lastBetCount = {}; // pool_id -> count of bets we've seen |
| 1236 | + |
| 1237 | +function addActivity(text, type) { |
| 1238 | + activityItems.unshift({ text, type, time: Date.now() }); |
| 1239 | + if (activityItems.length > 10) activityItems.length = 10; |
| 1240 | + renderActivity(); |
| 1241 | +} |
| 1242 | + |
| 1243 | +function renderActivity() { |
1233 | 1244 | const list = document.getElementById('activity-list'); |
1234 | | - const rounds = data.bracket?.rounds || []; |
1235 | | - const results = []; |
| 1245 | + if (activityItems.length === 0) { |
| 1246 | + list.innerHTML = '<li>Waiting for bets...</li>'; |
| 1247 | + return; |
| 1248 | + } |
| 1249 | + list.innerHTML = activityItems.map(a => { |
| 1250 | + const cls = a.type === 'bet' ? 'style="color:#ff6b35;"' |
| 1251 | + : a.type === 'win' ? 'style="color:#00ff88;"' |
| 1252 | + : ''; |
| 1253 | + return `<li ${cls}>${a.text}</li>`; |
| 1254 | + }).join(''); |
| 1255 | +} |
1236 | 1256 |
|
| 1257 | +function updateActivity(data) { |
| 1258 | + // Add match results |
| 1259 | + const rounds = data.bracket?.rounds || []; |
1237 | 1260 | for (const r of rounds) { |
1238 | 1261 | for (const m of r) { |
1239 | 1262 | if ((m.status === 'complete' || m.status === 'coinflip') && m.winner) { |
| 1263 | + const key = `result-${m.round}-${m.slot}`; |
| 1264 | + if (activityItems.some(a => a._key === key)) continue; |
1240 | 1265 | const loser = (m.entry_a && m.winner.name === m.entry_a.name) ? m.entry_b : m.entry_a; |
1241 | 1266 | const label = m.status === 'coinflip' ? 'COIN' : 'WIN'; |
1242 | 1267 | const scoreStr = (m.score_a != null && m.score_b != null) |
1243 | | - ? ` (${m.score_a}-${m.score_b})` |
1244 | | - : ''; |
1245 | | - results.push({ |
| 1268 | + ? ` (${m.score_a}-${m.score_b})` : ''; |
| 1269 | + const item = { |
1246 | 1270 | text: `${escHtml(m.winner.name)} ${label}${scoreStr} vs ${loser ? escHtml(loser.name) : 'BYE'}`, |
1247 | | - round: m.round, |
1248 | | - slot: m.slot, |
1249 | | - }); |
| 1271 | + type: 'win', time: Date.now(), _key: key, |
| 1272 | + }; |
| 1273 | + activityItems.unshift(item); |
1250 | 1274 | } |
1251 | 1275 | } |
1252 | 1276 | } |
| 1277 | + if (activityItems.length > 10) activityItems.length = 10; |
| 1278 | + renderActivity(); |
1253 | 1279 |
|
1254 | | - if (results.length === 0) { |
1255 | | - list.innerHTML = '<li>No results yet</li>'; |
1256 | | - return; |
| 1280 | + // Poll for bet activity on current pool |
| 1281 | + pollBetActivity(data); |
| 1282 | +} |
| 1283 | + |
| 1284 | +async function pollBetActivity(data) { |
| 1285 | + // Find current pool_id from playing match |
| 1286 | + const rounds = data.bracket?.rounds || []; |
| 1287 | + let poolId = null; |
| 1288 | + let entryA = null, entryB = null; |
| 1289 | + for (const r of rounds) { |
| 1290 | + for (const m of r) { |
| 1291 | + if (m.pool_id && (m.status === 'playing' || m.status === 'complete')) { |
| 1292 | + poolId = m.pool_id; |
| 1293 | + entryA = m.entry_a; |
| 1294 | + entryB = m.entry_b; |
| 1295 | + } |
| 1296 | + } |
1257 | 1297 | } |
| 1298 | + if (!poolId) return; |
1258 | 1299 |
|
1259 | | - // Show most recent first, limit to 6 |
1260 | | - results.reverse(); |
1261 | | - list.innerHTML = results.slice(0, 6).map(r => |
1262 | | - `<li>${r.text}</li>` |
1263 | | - ).join(''); |
| 1300 | + try { |
| 1301 | + const resp = await fetch(`${arenaBase}/pools/${poolId}/bets`); |
| 1302 | + if (!resp.ok) return; |
| 1303 | + const result = await resp.json(); |
| 1304 | + const bets = result.bets || []; |
| 1305 | + const prev = lastBetCount[poolId] || 0; |
| 1306 | + |
| 1307 | + if (bets.length > prev) { |
| 1308 | + // New bets since last poll |
| 1309 | + const newBets = bets.slice(prev); |
| 1310 | + for (const b of newBets) { |
| 1311 | + const side = b.betOnA ? (entryA?.name || 'Player A') : (entryB?.name || 'Player B'); |
| 1312 | + const addr = b.bettor.slice(0, 6) + '...' + b.bettor.slice(-4); |
| 1313 | + addActivity(`${addr} bet ${b.amount_mon} MON on ${escHtml(side)}`, 'bet'); |
| 1314 | + } |
| 1315 | + } |
| 1316 | + lastBetCount[poolId] = bets.length; |
| 1317 | + } catch (e) { /* silent */ } |
1264 | 1318 | } |
1265 | 1319 |
|
1266 | 1320 | // ── Live Match WebSocket Stream ─────────────────────────────── |
|
0 commit comments