MediaWiki:Common.js: различия между версиями

Живой статус игрового сервера
Обновление живого статуса сервера
Строка 1: Строка 1:
(() => {
(() => {
     const status = document.getElementById('rs-server-status');
     const root = document.getElementById('rs-server-status');


     if (!status) {
     if (!root) {
         return;
         return;
     }
     }


     const players = document.getElementById('rs-status-players');
     const onlineText = document.getElementById('rs-status-online');
     const maxPlayers = document.getElementById('rs-status-max');
     const stateText = document.getElementById('rs-status-state');
     const map = document.getElementById('rs-status-map');
     const mapText = document.getElementById('rs-status-map');
     const preset = document.getElementById('rs-status-preset');
     const presetText = document.getElementById('rs-status-preset');
     const label = document.getElementById('rs-status-label');
    const playersText = document.getElementById('rs-status-players');
    const maxText = document.getElementById('rs-status-max');
     const fill = document.getElementById('rs-status-fill');


     async function updateServerStatus() {
    function clampPercent(value) {
        if (!Number.isFinite(value)) {
            return 0;
        }
        if (value < 0) {
            return 0;
        }
        if (value > 100) {
            return 100;
        }
        return value;
    }
 
    function setOffline() {
        root.classList.remove('rs-home-status--online');
        root.classList.add('rs-home-status--offline');
 
        onlineText.textContent = 'Оффлайн';
        stateText.textContent = 'Недоступен';
        mapText.textContent = '—';
        presetText.textContent = '—';
        playersText.textContent = '0';
        maxText.textContent = '0';
        fill.style.width = '0%';
    }
 
    function setOnline(data) {
        root.classList.remove('rs-home-status--offline');
        root.classList.add('rs-home-status--online');
 
        const players = Number.isInteger(data.players) ? data.players : 0;
        const maxPlayers = Number.isInteger(data.soft_max_players) ? data.soft_max_players : 0;
 
        const map = (typeof data.map === 'string' && data.map.trim())
            ? data.map.trim()
            : '—';
 
        const preset = (typeof data.preset === 'string' && data.preset.trim())
            ? data.preset.trim()
            : '—';
 
        const inRound = map !== '—';
        const percent = maxPlayers > 0 ? clampPercent((players / maxPlayers) * 100) : 0;
 
        onlineText.textContent = 'Онлайн';
        stateText.textContent = inRound ? 'Идёт раунд' : 'Ожидание раунда';
        mapText.textContent = map;
        presetText.textContent = preset;
        playersText.textContent = String(players);
        maxText.textContent = String(maxPlayers);
        fill.style.width = percent.toFixed(0) + '%';
    }
 
     async function updateStatus() {
         try {
         try {
             const response = await fetch('/server-status', {
             const response = await fetch('/server-status', {
Строка 22: Строка 77:


             if (!response.ok) {
             if (!response.ok) {
                 throw new Error(`HTTP ${response.status}`);
                 throw new Error('HTTP ' + response.status);
             }
             }


             const data = await response.json();
             const data = await response.json();
 
             setOnline(data);
            players.textContent =
         } catch (err) {
                Number.isInteger(data.players) ? data.players : '—';
             console.warn('RedStar status update failed:', err);
 
             setOffline();
            maxPlayers.textContent =
                Number.isInteger(data.soft_max_players)
                    ? data.soft_max_players
                    : '—';
 
            map.textContent =
                typeof data.map === 'string' && data.map.trim()
                    ? data.map
                    : '—';
 
             preset.textContent =
                typeof data.preset === 'string' && data.preset.trim()
                    ? data.preset
                    : '—';
 
            label.textContent = 'СЕРВЕР';
            status.classList.remove('rs-home-status--offline');
            status.classList.add('rs-home-status--online');
         } catch (error) {
             players.textContent = '—';
            maxPlayers.textContent = '—';
            map.textContent = '—';
            preset.textContent = 'Недоступен';
 
            label.textContent = 'СЕРВЕР';
            status.classList.remove('rs-home-status--online');
            status.classList.add('rs-home-status--offline');
 
             console.warn('RedStar server status unavailable:', error);
         }
         }
     }
     }


     updateServerStatus();
     updateStatus();
     window.setInterval(updateServerStatus, 30000);
     window.setInterval(updateStatus, 30000);
})();
})();

Версия от 14:26, 29 сентября 2026

(() => {
    const root = document.getElementById('rs-server-status');

    if (!root) {
        return;
    }

    const onlineText = document.getElementById('rs-status-online');
    const stateText = document.getElementById('rs-status-state');
    const mapText = document.getElementById('rs-status-map');
    const presetText = document.getElementById('rs-status-preset');
    const playersText = document.getElementById('rs-status-players');
    const maxText = document.getElementById('rs-status-max');
    const fill = document.getElementById('rs-status-fill');

    function clampPercent(value) {
        if (!Number.isFinite(value)) {
            return 0;
        }
        if (value < 0) {
            return 0;
        }
        if (value > 100) {
            return 100;
        }
        return value;
    }

    function setOffline() {
        root.classList.remove('rs-home-status--online');
        root.classList.add('rs-home-status--offline');

        onlineText.textContent = 'Оффлайн';
        stateText.textContent = 'Недоступен';
        mapText.textContent = '—';
        presetText.textContent = '—';
        playersText.textContent = '0';
        maxText.textContent = '0';
        fill.style.width = '0%';
    }

    function setOnline(data) {
        root.classList.remove('rs-home-status--offline');
        root.classList.add('rs-home-status--online');

        const players = Number.isInteger(data.players) ? data.players : 0;
        const maxPlayers = Number.isInteger(data.soft_max_players) ? data.soft_max_players : 0;

        const map = (typeof data.map === 'string' && data.map.trim())
            ? data.map.trim()
            : '—';

        const preset = (typeof data.preset === 'string' && data.preset.trim())
            ? data.preset.trim()
            : '—';

        const inRound = map !== '—';
        const percent = maxPlayers > 0 ? clampPercent((players / maxPlayers) * 100) : 0;

        onlineText.textContent = 'Онлайн';
        stateText.textContent = inRound ? 'Идёт раунд' : 'Ожидание раунда';
        mapText.textContent = map;
        presetText.textContent = preset;
        playersText.textContent = String(players);
        maxText.textContent = String(maxPlayers);
        fill.style.width = percent.toFixed(0) + '%';
    }

    async function updateStatus() {
        try {
            const response = await fetch('/server-status', {
                cache: 'no-store',
                headers: {
                    'Accept': 'application/json'
                }
            });

            if (!response.ok) {
                throw new Error('HTTP ' + response.status);
            }

            const data = await response.json();
            setOnline(data);
        } catch (err) {
            console.warn('RedStar status update failed:', err);
            setOffline();
        }
    }

    updateStatus();
    window.setInterval(updateStatus, 30000);
})();