'use strict';
/* ═══════════════════════════════════════════════════════════════
Калькулятор скорости передачи данных - интерактив для 10 класса
═══════════════════════════════════════════════════════════════ */
(function () {
/* ── Таблица перевода размера в байты ─────────────────────────
Используем двоичные приставки, как принято для файлов. */
var SIZE_TO_BYTES = {
'KB': 1024,
'MB': 1024 * 1024,
'GB': 1024 * 1024 * 1024
};
/* ── Таблица перевода скорости в биты в секунду ─────────────
Для скорости используем десятичные приставки (стандарт связи). */
var SPEED_TO_BPS = {
'Kbps': 1000,
'Mbps': 1000 * 1000,
'Gbps': 1000 * 1000 * 1000
};
/* ── Таблица времени в секунды ─────────────────────────── */
var TIME_TO_SEC = {
'sec': 1,
'min': 60,
'hour': 3600
};
/* ── Быстрый доступ к элементу ─────────────────────────── */
function q(id) { return document.getElementById(id); }
/* ── Форматирование числа с разделителем ───────────────── */
function fmt(n, digits) {
if (!isFinite(n)) return '∞';
digits = (digits === undefined) ? 2 : digits;
return n.toLocaleString('ru-RU', {
minimumFractionDigits: 0,
maximumFractionDigits: digits
});
}
/* ── Форматирование времени в человеческий вид ─────────── */
function fmtTime(sec) {
if (!isFinite(sec) || sec < 0) return '-';
if (sec < 1) {
return fmt(sec * 1000, 0) + ' мс';
}
if (sec < 60) {
return fmt(sec, 2) + ' ' + plural(sec, ['секунда', 'секунды', 'секунд']);
}
if (sec < 3600) {
var m = Math.floor(sec / 60);
var s = Math.round(sec % 60);
return m + ' мин ' + s + ' с';
}
if (sec < 86400) {
var h = Math.floor(sec / 3600);
var m2 = Math.round((sec % 3600) / 60);
return h + ' ч ' + m2 + ' мин';
}
var d = Math.floor(sec / 86400);
var h2 = Math.round((sec % 86400) / 3600);
return d + ' ' + plural(d, ['день', 'дня', 'дней']) + ' ' + h2 + ' ч';
}
/* ── Форматирование скорости ───────────────────────────── */
function fmtSpeed(bps) {
if (!isFinite(bps) || bps <= 0) return '-';
if (bps < 1000) return fmt(bps, 2) + ' бит/с';
if (bps < 1000 * 1000) return fmt(bps / 1000, 2) + ' Кбит/с';
if (bps < 1000 * 1000 * 1000) return fmt(bps / 1e6, 2) + ' Мбит/с';
return fmt(bps / 1e9, 2) + ' Гбит/с';
}
/* ── Форматирование размера ────────────────────────────── */
function fmtSize(bytes) {
if (bytes < 1024) return fmt(bytes, 0) + ' Б';
if (bytes < 1024 * 1024) return fmt(bytes / 1024, 2) + ' КБ';
if (bytes < 1024 * 1024 * 1024) return fmt(bytes / (1024 * 1024), 2) + ' МБ';
return fmt(bytes / (1024 * 1024 * 1024), 2) + ' ГБ';
}
/* ── Русские склонения ─────────────────────────────────── */
function plural(n, forms) {
var m10 = n % 10;
var m100 = n % 100;
if (m10 === 1 && m100 !== 11) return forms[0];
if (m10 >= 2 && m10 <= 4 && (m100 < 10 || m100 >= 20)) return forms[1];
return forms[2];
}
/* ── Экранирование HTML ───────────────────────────────── */
function esc(s) {
return String(s).replace(/[&<>"']/g, function (c) {
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
});
}
/* ═══ РЕЖИМ 1: ВРЕМЯ ЗАГРУЗКИ ═══════════════════════════ */
function calcTime() {
var sizeVal = parseFloat(q('scTimeSize').value);
var sizeUnit = q('scTimeSizeUnit').value;
var speedVal = parseFloat(q('scTimeSpeed').value);
var speedUnit = q('scTimeSpeedUnit').value;
var resultEl = q('scTimeResult');
var resultSubEl = q('scTimeResultSub');
var stepsEl = q('scTimeSteps');
var compareEl = q('scTimeCompare');
if (!(sizeVal > 0) || !(speedVal > 0)) {
resultEl.textContent = '-';
resultSubEl.textContent = 'введите положительные числа';
stepsEl.innerHTML = '';
compareEl.innerHTML = '';
return;
}
/* 1. Переводим объём в байты */
var sizeBytes = sizeVal * SIZE_TO_BYTES[sizeUnit];
/* 2. Переводим объём в биты (умножаем на 8) */
var sizeBits = sizeBytes * 8;
/* 3. Переводим скорость в биты в секунду */
var speedBps = speedVal * SPEED_TO_BPS[speedUnit];
/* 4. Время в секундах */
var timeSec = sizeBits / speedBps;
/* Показываем результат */
resultEl.textContent = fmtTime(timeSec);
resultSubEl.textContent =
'файл ' + fmtSize(sizeBytes) + ' при скорости ' + fmtSpeed(speedBps) +
' (' + fmt(timeSec, 3) + ' секунд)';
/* Разбор по шагам */
var steps = [
'Переводим размер файла в байты: ' + fmt(sizeVal, 2) + ' ' + sizeUnit +
' = ' + fmt(sizeBytes, 0) + ' байт',
'Переводим байты в биты (умножаем на 8): ' + fmt(sizeBytes, 0) +
' × 8 = ' + fmt(sizeBits, 0) + ' бит',
'Переводим скорость в биты в секунду: ' + fmt(speedVal, 2) + ' ' +
speedUnit + ' = ' + fmt(speedBps, 0) + ' бит/с',
'Считаем время по формуле t = V / v:
' +
't = ' + fmt(sizeBits, 0) + ' / ' + fmt(speedBps, 0) + ' = ' +
fmt(timeSec, 3) + ' секунд',
'Округляем до удобного вида: ' + fmtTime(timeSec) + ''
];
renderSteps(stepsEl, steps);
/* Сравнение с технологиями */
renderTimeCompare(compareEl, sizeBits);
}
function renderTimeCompare(container, sizeBits) {
var techs = [
{ name: 'Dial-up', bps: 56 * 1000 },
{ name: '3G', bps: 2 * 1000 * 1000 },
{ name: '4G LTE', bps: 30 * 1000 * 1000 },
{ name: 'Wi-Fi 100', bps: 100 * 1000 * 1000 },
{ name: '5G', bps: 500 * 1000 * 1000 },
{ name: 'Оптоволокно', bps: 1000 * 1000 * 1000 }
];
/* Находим максимальное время для нормирования полосок */
var maxTime = 0;
techs.forEach(function (t) {
var sec = sizeBits / t.bps;
if (sec > maxTime) maxTime = sec;
});
var html = techs.map(function (t) {
var sec = sizeBits / t.bps;
var pct = maxTime > 0 ? Math.max(2, sec / maxTime * 100) : 0;
return '
' + fmt(sizeBytes, 0) + ' байт = ' +
fmt(sizeBits, 0) + ' бит',
'Желаемое время: ' + fmt(timeVal, 2) + ' ' + timeUnit +
' = ' + fmt(timeSec, 0) + ' секунд',
'Считаем нужную скорость по формуле v = V / t:' + fmt(sizeBits, 0) + ' / ' + fmt(timeSec, 0) + ' = ' +
fmt(speedBps, 0) + ' бит/с',
'Переводим в удобные единицы: ' + fmt(speedBps, 0) +
' бит/с = ' + fmt(speedMbps, 2) + ' Мбит/с',
'Итог: нужен тариф не ниже ' + fmt(speedMbps, 2) +
' Мбит/с (при условии идеального канала)'
];
renderSteps(stepsEl, steps);
}
/* ═══ ВСПОМОГАТЕЛЬНЫЕ ════════════════════════════════════ */
function renderSteps(container, steps) {
container.innerHTML = steps.map(function (text, i) {
return '