/* The costs page. * * Every figure is fetched from /api/fees, which the server renders from the * same schedule it charges. Nothing here is written by hand, so the published * terms cannot drift from the behaviour — if the operator changes the rake, * this page changes with it. */ const $ = (id) => document.getElementById(id); function el(tag, attrs, ...children) { const node = document.createElement(tag); for (const [k, v] of Object.entries(attrs || {})) { if (k === 'class') node.className = v; else if (k === 'text') node.textContent = v; else node.setAttribute(k, v); } for (const c of children) { if (c == null) continue; node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c); } return node; } async function load() { let d; try { d = await (await fetch('/api/fees')).json(); } catch { $('schedule').textContent = 'Could not load the fee schedule.'; return; } const s = d.schedule || {}; const grid = $('schedule'); const rows = [ ['taken from winnings', s.rake_percent], ['payouts rounded to', s.rounding_unit], ['most rounding can cost', s.worst_case_rounding_per_payout], ]; for (const [k, v] of rows) { grid.appendChild(el('div', {}, el('span', { class: 'k', text: k }), el('span', { class: 'v', text: v || '—' }))); } $('worst').textContent = s.worst_case_rounding_per_payout || '—'; const table = $('rtp-table'); const crash = d.crash_games || {}; table.appendChild(el('tr', {}, el('td', { text: 'Crash games' }), el('td', { text: crash.game_rtp_percent || '—' }), el('td', { class: 'rtp', text: crash.effective_percent || '—' }))); for (const t of d.scratch_tickets || []) { table.appendChild(el('tr', {}, el('td', { text: t.ticket }), el('td', { text: t.game_rtp_percent }), el('td', { class: 'rtp', text: t.effective_percent }))); } } load();