MediaWiki:Common.js: различия между версиями
Статус игрового сервера |
Живой статус и время раунда |
||
| Строка 15: | Строка 15: | ||
const fill = document.getElementById('rs-status-fill'); | const fill = document.getElementById('rs-status-fill'); | ||
function | let roundStart = null; | ||
let runLevel = 0; | |||
function formatDuration(milliseconds) { | |||
if (!Number.isFinite(milliseconds) || milliseconds < 0) { | |||
return '—'; | |||
} | |||
const totalMinutes = Math.floor(milliseconds / 60000); | |||
const hours = Math.floor(totalMinutes / 60); | |||
const minutes = totalMinutes % 60; | |||
if (hours > 0) { | |||
return `${hours} ч ${minutes} мин`; | |||
} | |||
return `${minutes} мин`; | |||
} | |||
function updateRoundTime() { | |||
if (runLevel !== 1 || roundStart === null) { | |||
time.textContent = '—'; | |||
return; | |||
} | |||
time.textContent = formatDuration(Date.now() - roundStart); | |||
} | |||
function setOffline() { | |||
root.classList.add('rs-home-status--offline'); | root.classList.add('rs-home-status--offline'); | ||
| Строка 26: | Строка 54: | ||
maxPlayers.textContent = '0'; | maxPlayers.textContent = '0'; | ||
fill.style.width = '0%'; | fill.style.width = '0%'; | ||
roundStart = null; | |||
runLevel = 0; | |||
} | } | ||
function | function setOnline(data) { | ||
root.classList.remove('rs-home-status--offline'); | root.classList.remove('rs-home-status--offline'); | ||
const currentPlayers = | const currentPlayers = | ||
Number.isInteger(data.players) ? data.players : 0; | Number.isInteger(data.players) | ||
? data.players | |||
: 0; | |||
const maximum = | const maximum = | ||
Number.isInteger(data.soft_max_players) | Number.isInteger(data.soft_max_players) | ||
? data.soft_max_players | ? data.soft_max_players | ||
: 0; | |||
runLevel = | |||
Number.isInteger(data.run_level) | |||
? data.run_level | |||
: 0; | : 0; | ||
online.textContent = 'Онлайн'; | online.textContent = 'Онлайн'; | ||
state.textContent = | switch (runLevel) { | ||
case 1: | |||
state.textContent = 'Идёт раунд'; | |||
: 'Ожидание раунда'; | break; | ||
case 2: | |||
state.textContent = 'Раунд завершён'; | |||
break; | |||
default: | |||
state.textContent = 'Ожидание раунда'; | |||
break; | |||
} | |||
map.textContent = | if (runLevel === 0) { | ||
typeof data.map === 'string' && data.map.trim() | map.textContent = '—'; | ||
} else { | |||
map.textContent = | |||
typeof data.map === 'string' && data.map.trim() | |||
? data.map.trim() | |||
: '—'; | |||
} | |||
preset.textContent = | preset.textContent = | ||
| Строка 60: | Строка 107: | ||
players.textContent = String(currentPlayers); | players.textContent = String(currentPlayers); | ||
maxPlayers.textContent = String(maximum); | maxPlayers.textContent = String(maximum); | ||
if ( | |||
runLevel === 1 && | |||
typeof data.round_start_time === 'string' && | |||
data.round_start_time.length > 0 | |||
) { | |||
const parsed = Date.parse(data.round_start_time); | |||
roundStart = Number.isNaN(parsed) ? null : parsed; | |||
} else { | |||
roundStart = null; | |||
} | |||
updateRoundTime(); | |||
const percent = | const percent = | ||
| Строка 66: | Строка 126: | ||
: 0; | : 0; | ||
fill.style.width = percent.toFixed( | fill.style.width = percent.toFixed(1) + '%'; | ||
} | } | ||
async function | async function updateStatus() { | ||
try { | try { | ||
const response = await fetch('/server-status', { | const response = await fetch('/server-status', { | ||
| Строка 79: | Строка 139: | ||
if (!response.ok) { | if (!response.ok) { | ||
throw new Error( | throw new Error(`HTTP ${response.status}`); | ||
} | } | ||
const data = await response.json(); | |||
setOnline(data); | |||
} catch (error) { | } catch (error) { | ||
console.warn('RedStar server status unavailable:', error); | console.warn('RedStar server status unavailable:', error); | ||
setOffline(); | |||
} | } | ||
} | } | ||
updateStatus(); | |||
window.setInterval( | |||
window.setInterval(updateStatus, 30000); | |||
window.setInterval(updateRoundTime, 1000); | |||
})(); | })(); | ||
Версия от 15:09, 29 сентября 2026
(() => {
const root = document.getElementById('rs-server-status');
if (!root) {
return;
}
const online = document.getElementById('rs-status-online');
const state = document.getElementById('rs-status-state');
const map = document.getElementById('rs-status-map');
const time = document.getElementById('rs-status-time');
const preset = document.getElementById('rs-status-preset');
const players = document.getElementById('rs-status-players');
const maxPlayers = document.getElementById('rs-status-max');
const fill = document.getElementById('rs-status-fill');
let roundStart = null;
let runLevel = 0;
function formatDuration(milliseconds) {
if (!Number.isFinite(milliseconds) || milliseconds < 0) {
return '—';
}
const totalMinutes = Math.floor(milliseconds / 60000);
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
if (hours > 0) {
return `${hours} ч ${minutes} мин`;
}
return `${minutes} мин`;
}
function updateRoundTime() {
if (runLevel !== 1 || roundStart === null) {
time.textContent = '—';
return;
}
time.textContent = formatDuration(Date.now() - roundStart);
}
function setOffline() {
root.classList.add('rs-home-status--offline');
online.textContent = 'Оффлайн';
state.textContent = 'Сервер недоступен';
map.textContent = '—';
time.textContent = '—';
preset.textContent = '—';
players.textContent = '0';
maxPlayers.textContent = '0';
fill.style.width = '0%';
roundStart = null;
runLevel = 0;
}
function setOnline(data) {
root.classList.remove('rs-home-status--offline');
const currentPlayers =
Number.isInteger(data.players)
? data.players
: 0;
const maximum =
Number.isInteger(data.soft_max_players)
? data.soft_max_players
: 0;
runLevel =
Number.isInteger(data.run_level)
? data.run_level
: 0;
online.textContent = 'Онлайн';
switch (runLevel) {
case 1:
state.textContent = 'Идёт раунд';
break;
case 2:
state.textContent = 'Раунд завершён';
break;
default:
state.textContent = 'Ожидание раунда';
break;
}
if (runLevel === 0) {
map.textContent = '—';
} else {
map.textContent =
typeof data.map === 'string' && data.map.trim()
? data.map.trim()
: '—';
}
preset.textContent =
typeof data.preset === 'string' && data.preset.trim()
? data.preset.trim()
: '—';
players.textContent = String(currentPlayers);
maxPlayers.textContent = String(maximum);
if (
runLevel === 1 &&
typeof data.round_start_time === 'string' &&
data.round_start_time.length > 0
) {
const parsed = Date.parse(data.round_start_time);
roundStart = Number.isNaN(parsed) ? null : parsed;
} else {
roundStart = null;
}
updateRoundTime();
const percent =
maximum > 0
? Math.min(100, Math.max(0, currentPlayers / maximum * 100))
: 0;
fill.style.width = percent.toFixed(1) + '%';
}
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 (error) {
console.warn('RedStar server status unavailable:', error);
setOffline();
}
}
updateStatus();
window.setInterval(updateStatus, 30000);
window.setInterval(updateRoundTime, 1000);
})();