Поддержать команду Зеркала
Беларусы на войне
  1. «Киберпартизаны» сообщили о новой масштабной утечке из КГБ. В базе — данные тысяч сотрудников и контактировавших с ведомством
  2. В парламент поступил законопроект от Лукашенко. Документ подготовлен по итогам масштабной ревизии законодательства
  3. Подоходный налог для некоторых беларусов хотят поднять до 40%. Стали известны подробности возможного новшества
  4. Кремль усиливает пропаганду о «полном успехе» в Украине и готовит россиян к победе любой ценой — ISW
  5. Для этих работников несколько лет назад ввели ужесточения, им тогда припомнили в том числе политику. Чиновники снова взялись за них
  6. «Это не та Беларусь, которая была до 2020 года. Совсем не та». Поговорили с дважды политзаключенным, который недавно уехал из страны
  7. Доллар готовится к быстрому рывку: какой курс будет в конце октября? Прогноз по валютам
  8. «Дотошно досматривали и на разговор вызывали». На границе Беларуси продолжаются допросы с проверками телефонов
  9. На фронте погиб воевавший на стороне России сын экс-кандидата в президенты Беларуси Дмитрия Усса — «Наша Ніва»
  10. Полиция Таиланда установила личность пропавшей в Мьянме беларуски
  11. В ГАИ предложили ужесточить ответственность для некоторых водителей
  12. «Советский Союз — это фашистский застенок», — считал первый ректор БГУ. Рассказываем об этом смелом ученом, влюбившемся в Беларусь
  13. Почему Лукашенко так задели заправки? Кризис на АЗС однажды уже вызвал массовые протесты в Беларуси — вспоминаем, как это было
  14. «Строительство оказалось нерациональным». В минском метро объяснили, почему станции «Профсоюзная» не будет


/

В прошедшие выходные на выездах из Беларуси у границ с Польшей и Литвой снова выросли очереди из легковых автомобилей (а кое-где — и автобусов). «Зеркало» проанализировало официальные данные и нашло дни и часы, в которые шанс «застрять» на границе самый большой, а также периоды, когда можно проскочить быстрее всего.

Изображение носит иллюстративный характер. Проверка легкового автомобиля на пункте пропуска в Мядининкае, Литва. Фото: Reuters
Изображение носит иллюстративный характер. Проверка легкового автомобиля на пункте пропуска в Мядининкае, Литва. Фото: Reuters
Как мы считали? Госпогранкомитет Беларуси каждые два часа публикует данные о том, сколько автомобилей ожидает выезда из страны. Мы проанализировали информацию ГПК за последние четыре недели по каждому из четырех пунктов пропуска, открытых для легковушек и автобусов:
  • «Брест» — на границе с Польшей,

  • «Каменный Лог» и «Бенякони» — на границе с Литвой,

  • «Григоровщина» — на границе с Латвией.

Для «Григоровщины» анализ получился самым коротким: за последние недели в данных ГПК значились только нули. Похожая ситуация с автобусами на пунктах пропуска в Литву — почти все время очереди для них не фиксируются.

«Брест»

«Брест» — пункт пропуска с самой напряженной ситуацией, очередь на выезд там есть почти всегда. С октября 2024 года в «Бресте» действует новая система: водители легковых автомобилей не ждут на дороге, а могут уехать после регистрации и вернуться, когда подойдет пора пересекать границу. Следить за положением автомобиля в виртуальной очереди можно через специальный сайт (и там же — оценить, сколько примерно осталось ждать).

Судя по данным ГПК, последние четыре недели очереди из легковых авто были не такими большими, а в какие-то моменты их даже не было (например, вечером 8 марта и утром 9-го). Однако в прошедшие несколько дней они только росли.

 

На основании данных за последние четыре недели мы подсчитали самое «горячее» время. Это вечер воскресенья, особенно после 18 часов. В среднем в эти часы проезда ожидает по 500−600 легковых автомобилей.

Самые «легкие» дни для выезда из Беларуси через «Брест» — пятница и суббота. В эти периоды в очереди обычно около 200 авто.

 

Администраторы зоны ожидания делятся информацией о том, сколько авто оформлено за сутки. Так можно пересчитать количество машин в часы ожидания. К примеру, на 20.00 проезда ждут 1130 легковушек, а за последние сутки оформили 464. Значит, если регистрироваться сейчас, то на проезд уйдет примерно 2,4 суток.

Очереди из автобусов на выезде через «Брест» есть не всегда. «Худшее» время для них — все воскресенье. В среднем на протяжении этого дня в очереди постоянно стоит около 10 автобусов. Час пик — вечер, особенно после 22 часов.

А вот лучшие часы — в будние дни. Например, в 8 утра во вторник, среду или четверг особого ажиотажа в автобусной очереди не наблюдается.

 

«Каменный Лог»

Больше всего желающих выехать из Беларуси на легковых авто через «Каменный Лог» — вечером воскресенья. После 18 часов на выезд скапливается обычно 40−50 авто.

Еще один пик числа выезжающих — вторая половина четверга, очереди тоже растягиваются, как правило, на 40−50 легковушек. А вот наименее нагруженный день на этом пропускном пункте — суббота, почти весь день очереди нулевые.

 

Очереди из автобусов в «Каменном Логе», напомним, почти не фиксируются. Судя по отчетам путешественников в тематических чатах, автобусы сейчас проходят границу через «Каменный Лог» примерно за час-два.

«Бенякони»

В этом пункте пропуска очереди легковушек сравнительно небольшие. «Худшее» время — это снова же вечер воскресенья, когда в среднем выезда ожидает около 20−25 авто. Небольшой пик очередей также есть в четверг во второй половине дня, тогда ожидают выезда по 10−15 автомобилей.

Лучшее время — вся суббота, а также все утренние часы — есть шанс, что ждать в принципе не придется.

 

Очереди из автобусов в пункте пропуска «Бенякони» также не фиксируются. Путешественники в тематических чатах делятся, что пройти досмотры получается примерно за 2−3 часа.

Время: ${d.date.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}

В очереди: ${d.count}` }; // Объединяем настройки по умолчанию с пользовательскими const cfg = { ...defaultConfig, ...config }; // Находим контейнер const container = d3.select(`#${containerId}`); container.html(''); // Очищаем контейнер // Добавляем заголовок container.append('div') .attr('class', 'heatmap-title') .style('font-size', '18px') .style('font-weight', 'bold') .style('margin-bottom', '10px') .style('text-align', 'center') .text(cfg.title); // Определяем размеры в зависимости от ширины экрана const containerWidth = container.node().getBoundingClientRect().width; const isMobile = containerWidth <= cfg.mobileBreakpoint; const width = containerWidth - 30; // Учитываем внутренние отступы контейнера const height = cfg.height; // Создаем SVG элемент const svg = container.append('svg') .attr('width', width) .attr('height', height) .append('g') .attr('transform', `translate(${cfg.margin.left},${cfg.margin.top})`); // Задаем размеры графика const chartWidth = width - cfg.margin.left - cfg.margin.right; const chartHeight = height - cfg.margin.top - cfg.margin.bottom; // Создаем шкалы const x = d3.scaleTime() .domain(d3.extent(data, d => d.date)) .range([0, chartWidth]); const y = d3.scaleLinear() .domain([0, d3.max(data, d => d.count) * 1.1]) // Добавляем 10% сверху для наглядности .range([chartHeight, 0]); // Добавляем оси svg.append('g') .attr('transform', `translate(0,${chartHeight})`) .style('font-size', isMobile ? '10px' : '12px') .call(d3.axisBottom(x) .ticks(isMobile ? 5 : 10) .tickFormat(d => { const formatDay = d3.timeFormat('%d.%m'); return formatDay(d); })); svg.append('g') .style('font-size', isMobile ? '10px' : '12px') .call(d3.axisLeft(y)); // Добавляем сетку svg.append('g') .attr('class', 'grid') .attr('transform', `translate(0,${chartHeight})`) .style('stroke', cfg.gridColor) .style('stroke-opacity', 0.3) .style('shape-rendering', 'crispEdges') .call(d3.axisBottom(x) .ticks(10) .tickSize(-chartHeight) .tickFormat('')); svg.append('g') .attr('class', 'grid') .style('stroke', cfg.gridColor) .style('stroke-opacity', 0.3) .style('shape-rendering', 'crispEdges') .call(d3.axisLeft(y) .ticks(10) .tickSize(-chartWidth) .tickFormat('')); // Создаем всплывающую подсказку (tooltip) const tooltip = d3.select('body').append('div') .attr('class', 'tooltip') .style('position', 'absolute') .style('background-color', 'rgba(255, 255, 255, 0.9)') .style('border', '1px solid #ddd') .style('padding', '10px') .style('border-radius', '4px') .style('pointer-events', 'none') .style('font-size', '14px') .style('box-shadow', '0 2px 4px rgba(0, 0, 0, 0.1)') .style('z-index', '10') .style('max-width', '200px') .style('display', 'none'); // Создаем линию const line = d3.line() .x(d => x(d.date)) .y(d => y(d.count)) .curve(d3.curveMonotoneX); // Сглаживаем линию // Добавляем область под линией svg.append('path') .datum(data) .attr('fill', cfg.lineColor) .attr('fill-opacity', 0.1) .attr('d', d3.area() .x(d => x(d.date)) .y0(chartHeight) .y1(d => y(d.count)) .curve(d3.curveMonotoneX)); // Добавляем линию svg.append('path') .datum(data) .attr('fill', 'none') .attr('stroke', cfg.lineColor) .attr('stroke-width', 2) .attr('d', line); // Добавляем точки для интерактивности const dots = svg.selectAll('.dot') .data(data) .enter() .append('circle') .attr('class', 'dot') .attr('cx', d => x(d.date)) .attr('cy', d => y(d.count)) .attr('r', 3) .attr('fill', cfg.lineColor) .style('opacity', 0) // Скрываем точки по умолчанию .on('mouseover', function(event, d) { d3.select(this) .transition() .duration(100) .attr('r', 5) .style('opacity', 1); tooltip .style('display', 'block') .html(cfg.tooltipFormat(d)) .style('left', (event.pageX + 10) + 'px') .style('top', (event.pageY - 28) + 'px'); }) .on('mousemove', function(event, d) { tooltip .style('left', (event.pageX + 10) + 'px') .style('top', (event.pageY - 28) + 'px'); }) .on('mouseout', function() { d3.select(this) .transition() .duration(100) .attr('r', 3) .style('opacity', 0); tooltip .style('display', 'none'); }); // Добавляем область для отслеживания мыши по всему графику svg.append('rect') .attr('width', chartWidth) .attr('height', chartHeight) .style('fill', 'none') .style('pointer-events', 'all') .on('mousemove', function(event) { const [mouseX] = d3.pointer(event); const x0 = x.invert(mouseX); // Находим ближайшую точку let i = d3.bisector(d => d.date).left(data, x0, 1); const d0 = data[i - 1]; const d1 = data[i]; if (!d0 || !d1) return; const d = x0 - d0.date > d1.date - x0 ? d1 : d0; // Отображаем точку и тултип dots.style('opacity', 0); dots.filter(dot => dot === d) .style('opacity', 1) .attr('r', 5); tooltip .style('display', 'block') .html(cfg.tooltipFormat(d)) .style('left', (event.pageX + 10) + 'px') .style('top', (event.pageY - 28) + 'px'); }) .on('mouseout', function() { dots.style('opacity', 0).attr('r', 3); tooltip.style('display', 'none'); }); // Добавляем подписи осей svg.append('text') .attr('transform', `translate(${chartWidth / 2}, ${chartHeight + 40})`) .style('text-anchor', 'middle') .style('font-size', isMobile ? '12px' : '14px') .text('Дата'); svg.append('text') .attr('transform', 'rotate(-90)') .attr('y', -40) .attr('x', -chartHeight / 2) .style('text-anchor', 'middle') .style('font-size', isMobile ? '12px' : '14px') .text('Количество автомобилей в очереди'); // Функция для обновления размеров при изменении размера окна function updateDimensions() { const newContainerWidth = container.node().getBoundingClientRect().width; const newIsMobile = newContainerWidth <= cfg.mobileBreakpoint; if (newIsMobile !== isMobile || Math.abs(newContainerWidth - containerWidth) > 50) { // Если изменился тип устройства или значительно изменилась ширина, перерисовываем график createLineChart(containerId, data, config); } } // Слушаем изменение размера окна window.addEventListener('resize', updateDimensions); } // Создаем линейный график после загрузки страницы document.addEventListener('DOMContentLoaded', function() { createLineChart('linechart-container', brestLineData, { title: 'Динамика очередей в пункте пропуска «Брест» (февраль-март 2025 г.)', lineColor: '#2a5a8a', tooltipFormat: (d) => { const dateFormat = new Intl.DateTimeFormat('ru', { day: '2-digit', month: '2-digit', year: 'numeric' }); const timeFormat = new Intl.DateTimeFormat('ru', { hour: '2-digit', minute: '2-digit' }); return `Дата: ${dateFormat.format(d.date)}

Время: ${timeFormat.format(d.date)}

В очереди: ${d.count} авто`; } }); }); // Глобальный объект для хранения всех тултипов const tooltips = {}; // Функция для создания тепловой карты function createHeatmap(containerId, data, config) { // Настройки по умолчанию const defaultConfig = { title: 'Тепловая карта', width: 720, mobileBreakpoint: 767, height: 400, margin: { top: 80, right: 25, bottom: 50, left: 60 }, colors: ['#1a9850', '#66bd63', '#a6d96a', '#d9ef8b', '#fee08b', '#fdae61', '#f46d43', '#d73027'], tooltipFormat: (d) => `${d.x}: ${d.y}

В очереди: ${d.value}` }; // Объединяем настройки по умолчанию с пользовательскими const cfg = { ...defaultConfig, ...config }; // Находим контейнер const container = d3.select(`#${containerId}`); container.html(''); // Очищаем контейнер // Добавляем заголовок container.append('div') .attr('class', 'heatmap-title') .style('font-size', '18px') .style('font-weight', 'bold') .style('margin-bottom', '10px') .style('text-align', 'center') .text(cfg.title); // Определяем размеры в зависимости от ширины экрана const containerWidth = container.node().getBoundingClientRect().width; const isMobile = containerWidth <= cfg.mobileBreakpoint; const width = containerWidth - 30; // Учитываем внутренние отступы контейнера const cellWidth = Math.floor((width - cfg.margin.left - cfg.margin.right) / data.xLabels.length); const cellHeight = Math.floor((cfg.height - cfg.margin.top - cfg.margin.bottom) / data.yLabels.length); const height = cellHeight * data.yLabels.length + cfg.margin.top + cfg.margin.bottom; // Создаем SVG элемент const svg = container.append('svg') .attr('width', width) .attr('height', height) .append('g') .attr('transform', `translate(${cfg.margin.left},${cfg.margin.top})`); // Создаем шкалы const x = d3.scaleBand() .range([0, width - cfg.margin.left - cfg.margin.right]) .domain(data.xLabels) .padding(0.05); const y = d3.scaleBand() .range([0, height - cfg.margin.top - cfg.margin.bottom]) .domain(data.yLabels) .padding(0.05); // Определяем цветовую шкалу const minValue = d3.min(data.values, d => d.value); const maxValue = d3.max(data.values, d => d.value); const colorScale = d3.scaleQuantile() .domain([minValue, maxValue]) .range(cfg.colors); // Добавляем оси svg.append('g') .style('font-size', isMobile ? '10px' : '12px') .call(d3.axisTop(x)) .selectAll('text') .style('text-anchor', 'start') .attr('dx', '.8em') .attr('dy', '.15em') .attr('transform', 'rotate(-45)'); svg.append('g') .style('font-size', isMobile ? '10px' : '12px') .call(d3.axisLeft(y)); // Создаем уникальный идентификатор для тултипа const tooltipId = `tooltip-${containerId}`; // Создаем всплывающую подсказку, если её ещё нет if (!tooltips[tooltipId]) { tooltips[tooltipId] = d3.select('body').append('div') .attr('class', 'tooltip') .attr('id', tooltipId) .style('max-height', '100px') // Ограничиваем высоту .style('overflow-y', 'auto'); // Добавляем прокрутку при необходимости } const tooltip = tooltips[tooltipId]; // Добавляем ячейки svg.selectAll() .data(data.values) .enter() .append('rect') .attr('x', d => x(d.x)) .attr('y', d => y(d.y)) .attr('width', x.bandwidth()) .attr('height', y.bandwidth()) .attr('class', 'cell') .style('fill', d => colorScale(d.value)) .on('mouseover', function(event, d) { tooltip .style('display', 'block') .html(cfg.tooltipFormat(d)) .style('left', (event.pageX + 10) + 'px') .style('top', (event.pageY - 28) + 'px'); d3.select(this).style('stroke-width', '2px'); }) .on('mousemove', function(event, d) { tooltip .style('left', (event.pageX + 10) + 'px') .style('top', (event.pageY - 28) + 'px'); }) .on('mouseout', function() { tooltip .style('display', 'none'); d3.select(this).style('stroke-width', '1px'); }); // Функция для обновления размеров при изменении размера окна function updateDimensions() { const newContainerWidth = container.node().getBoundingClientRect().width; const newIsMobile = newContainerWidth <= cfg.mobileBreakpoint; if (newIsMobile !== isMobile || Math.abs(newContainerWidth - containerWidth) > 50) { // Если изменился тип устройства или значительно изменилась ширина, перерисовываем график createHeatmap(containerId, data, config); } } // Слушаем изменение размера окна window.addEventListener('resize', updateDimensions); // Возвращаем функцию для удаления обработчика return function cleanup() { window.removeEventListener('resize', updateDimensions); }; } // Данные для пункта пропуска "Брест" const brestData = { xLabels: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'], yLabels: ['0:00', '2:00', '4:00', '6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'], values: [ // Понедельник {x: 'Понедельник', y: '0:00', value: 475}, {x: 'Понедельник', y: '2:00', value: 461.25}, {x: 'Понедельник', y: '4:00', value: 415}, {x: 'Понедельник', y: '6:00', value: 391.25}, {x: 'Понедельник', y: '8:00', value: 351.25}, {x: 'Понедельник', y: '10:00', value: 332.5}, {x: 'Понедельник', y: '12:00', value: 348.75}, {x: 'Понедельник', y: '14:00', value: 367.5}, {x: 'Понедельник', y: '16:00', value: 391.25}, {x: 'Понедельник', y: '18:00', value: 415}, {x: 'Понедельник', y: '20:00', value: 427.5}, {x: 'Понедельник', y: '22:00', value: 425}, // Вторник {x: 'Вторник', y: '0:00', value: 416.75}, {x: 'Вторник', y: '2:00', value: 398}, {x: 'Вторник', y: '4:00', value: 368.75}, {x: 'Вторник', y: '6:00', value: 341.25}, {x: 'Вторник', y: '8:00', value: 317.5}, {x: 'Вторник', y: '10:00', value: 297.5}, {x: 'Вторник', y: '12:00', value: 308.75}, {x: 'Вторник', y: '14:00', value: 300}, {x: 'Вторник', y: '16:00', value: 290}, {x: 'Вторник', y: '18:00', value: 308.75}, {x: 'Вторник', y: '20:00', value: 311.25}, {x: 'Вторник', y: '22:00', value: 347.5}, // Среда {x: 'Среда', y: '0:00', value: 371.25}, {x: 'Среда', y: '2:00', value: 375.25}, {x: 'Среда', y: '4:00', value: 354.5}, {x: 'Среда', y: '6:00', value: 320}, {x: 'Среда', y: '8:00', value: 292.5}, {x: 'Среда', y: '10:00', value: 280}, {x: 'Среда', y: '12:00', value: 282.5}, {x: 'Среда', y: '14:00', value: 283.75}, {x: 'Среда', y: '16:00', value: 278.75}, {x: 'Среда', y: '18:00', value: 263.75}, {x: 'Среда', y: '20:00', value: 297.5}, {x: 'Среда', y: '22:00', value: 323.75}, // Четверг {x: 'Четверг', y: '0:00', value: 360}, {x: 'Четверг', y: '2:00', value: 362.25}, {x: 'Четверг', y: '4:00', value: 344.75}, {x: 'Четверг', y: '6:00', value: 323.75}, {x: 'Четверг', y: '8:00', value: 303.75}, {x: 'Четверг', y: '10:00', value: 285}, {x: 'Четверг', y: '12:00', value: 273.75}, {x: 'Четверг', y: '14:00', value: 272.5}, {x: 'Четверг', y: '16:00', value: 277.5}, {x: 'Четверг', y: '18:00', value: 291.75}, {x: 'Четверг', y: '20:00', value: 298.75}, {x: 'Четверг', y: '22:00', value: 308.75}, // Пятница {x: 'Пятница', y: '0:00', value: 327.5}, {x: 'Пятница', y: '2:00', value: 326.75}, {x: 'Пятница', y: '4:00', value: 310.25}, {x: 'Пятница', y: '6:00', value: 270}, {x: 'Пятница', y: '8:00', value: 240.25}, {x: 'Пятница', y: '10:00', value: 235}, {x: 'Пятница', y: '12:00', value: 226.25}, {x: 'Пятница', y: '14:00', value: 212.5}, {x: 'Пятница', y: '16:00', value: 208.75}, {x: 'Пятница', y: '18:00', value: 212.25}, {x: 'Пятница', y: '20:00', value: 207}, {x: 'Пятница', y: '22:00', value: 236.75}, // Суббота {x: 'Суббота', y: '0:00', value: 243.5}, {x: 'Суббота', y: '2:00', value: 244.25}, {x: 'Суббота', y: '4:00', value: 233}, {x: 'Суббота', y: '6:00', value: 195.75}, {x: 'Суббота', y: '8:00', value: 181.25}, {x: 'Суббота', y: '10:00', value: 186.25}, {x: 'Суббота', y: '12:00', value: 196.25}, {x: 'Суббота', y: '14:00', value: 220}, {x: 'Суббота', y: '16:00', value: 242.5}, {x: 'Суббота', y: '18:00', value: 268.75}, {x: 'Суббота', y: '20:00', value: 285}, {x: 'Суббота', y: '22:00', value: 302.5}, // Воскресенье {x: 'Воскресенье', y: '0:00', value: 312.5}, {x: 'Воскресенье', y: '2:00', value: 303}, {x: 'Воскресенье', y: '4:00', value: 293.5}, {x: 'Воскресенье', y: '6:00', value: 282.5}, {x: 'Воскресенье', y: '8:00', value: 286.25}, {x: 'Воскресенье', y: '10:00', value: 316.25}, {x: 'Воскресенье', y: '12:00', value: 375}, {x: 'Воскресенье', y: '14:00', value: 427.5}, {x: 'Воскресенье', y: '16:00', value: 498.75}, {x: 'Воскресенье', y: '18:00', value: 588.75}, {x: 'Воскресенье', y: '20:00', value: 608.75}, {x: 'Воскресенье', y: '22:00', value: 646.25} ] }; // Создаем тепловую карту для пункта пропуска "Брест" createHeatmap('heatmap-container-1', brestData, { title: 'Тепловая карта очередей в пункте пропуска "Брест"', tooltipFormat: (d) => `День: ${d.x}

Время: ${d.y}

В очереди: ${d.value}`, colors: ['#1a9850', '#66bd63', '#a6d96a', '#d9ef8b', '#fee08b', '#fdae61', '#f46d43', '#d73027'], height: 420, margin: { top: 80, right: 25, bottom: 50, left: 60 } }); // Функция для добавления новых данных и создания тепловой карты function addCheckpointData(containerId, checkpointName, data) { createHeatmap(containerId, data, { title: `Тепловая карта очередей в пункте пропуска «${checkpointName}»`, tooltipFormat: (d) => `День: ${d.x}

Время: ${d.y}

В очереди: ${d.value}`, colors: ['#1a9850', '#66bd63', '#a6d96a', '#d9ef8b', '#fee08b', '#fdae61', '#f46d43', '#d73027'], height: 420, margin: { top: 80, right: 25, bottom: 50, left: 60 } }); } // Создаем глобальный объект для управления данными пунктов пропуска window.checkpointManager = { addCheckpointData: addCheckpointData }; // Пример данных для других пунктов пропуска (будут заменены реальными данными) const sampleData = { xLabels: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'], yLabels: ['0:00', '2:00', '4:00', '6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'], values: [ // Пример данных {x: 'Понедельник', y: '0:00', value: 100}, {x: 'Понедельник', y: '2:00', value: 120} // Здесь будут полные данные ] }; // Данные для пункта пропуска "Брест" (автобусы) const brestBusData = { xLabels: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'], yLabels: ['0:00', '2:00', '4:00', '6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'], values: [ // 0:00 {x: 'Понедельник', y: '0:00', value: 5}, {x: 'Вторник', y: '0:00', value: 0.25}, {x: 'Среда', y: '0:00', value: 1.25}, {x: 'Четверг', y: '0:00', value: 0}, {x: 'Пятница', y: '0:00', value: 2}, {x: 'Суббота', y: '0:00', value: 1.5}, {x: 'Воскресенье', y: '0:00', value: 9}, // 2:00 {x: 'Понедельник', y: '2:00', value: 4.5}, {x: 'Вторник', y: '2:00', value: 1.25}, {x: 'Среда', y: '2:00', value: 2.75}, {x: 'Четверг', y: '2:00', value: 1.25}, {x: 'Пятница', y: '2:00', value: 2}, {x: 'Суббота', y: '2:00', value: 6}, {x: 'Воскресенье', y: '2:00', value: 11.5}, // 4:00 {x: 'Понедельник', y: '4:00', value: 2}, {x: 'Вторник', y: '4:00', value: 0}, {x: 'Среда', y: '4:00', value: 0}, {x: 'Четверг', y: '4:00', value: 0}, {x: 'Пятница', y: '4:00', value: 1.5}, {x: 'Суббота', y: '4:00', value: 8.5}, {x: 'Воскресенье', y: '4:00', value: 13}, // 6:00 {x: 'Понедельник', y: '6:00', value: 5.5}, {x: 'Вторник', y: '6:00', value: 0}, {x: 'Среда', y: '6:00', value: 0}, {x: 'Четверг', y: '6:00', value: 0}, {x: 'Пятница', y: '6:00', value: 0.75}, {x: 'Суббота', y: '6:00', value: 2.25}, {x: 'Воскресенье', y: '6:00', value: 13.75}, // 8:00 {x: 'Понедельник', y: '8:00', value: 3.5}, {x: 'Вторник', y: '8:00', value: 0}, {x: 'Среда', y: '8:00', value: 0}, {x: 'Четверг', y: '8:00', value: 0}, {x: 'Пятница', y: '8:00', value: 2.5}, {x: 'Суббота', y: '8:00', value: 6.25}, {x: 'Воскресенье', y: '8:00', value: 10.5}, // 10:00 {x: 'Понедельник', y: '10:00', value: 3.5}, {x: 'Вторник', y: '10:00', value: 0.5}, {x: 'Среда', y: '10:00', value: 0}, {x: 'Четверг', y: '10:00', value: 0}, {x: 'Пятница', y: '10:00', value: 2.25}, {x: 'Суббота', y: '10:00', value: 5.5}, {x: 'Воскресенье', y: '10:00', value: 9.25}, // 12:00 {x: 'Понедельник', y: '12:00', value: 4.25}, {x: 'Вторник', y: '12:00', value: 2.25}, {x: 'Среда', y: '12:00', value: 0}, {x: 'Четверг', y: '12:00', value: 1.25}, {x: 'Пятница', y: '12:00', value: 4}, {x: 'Суббота', y: '12:00', value: 4.25}, {x: 'Воскресенье', y: '12:00', value: 8.5}, // 14:00 {x: 'Понедельник', y: '14:00', value: 4.5}, {x: 'Вторник', y: '14:00', value: 2.75}, {x: 'Среда', y: '14:00', value: 1.25}, {x: 'Четверг', y: '14:00', value: 5}, {x: 'Пятница', y: '14:00', value: 5.5}, {x: 'Суббота', y: '14:00', value: 5.75}, {x: 'Воскресенье', y: '14:00', value: 11.5}, // 16:00 {x: 'Понедельник', y: '16:00', value: 2.75}, {x: 'Вторник', y: '16:00', value: 1.5}, {x: 'Среда', y: '16:00', value: 3.25}, {x: 'Четверг', y: '16:00', value: 5.25}, {x: 'Пятница', y: '16:00', value: 3.75}, {x: 'Суббота', y: '16:00', value: 7.5}, {x: 'Воскресенье', y: '16:00', value: 9.75}, // 18:00 {x: 'Понедельник', y: '18:00', value: 2.5}, {x: 'Вторник', y: '18:00', value: 1}, {x: 'Среда', y: '18:00', value: 2}, {x: 'Четверг', y: '18:00', value: 3.75}, {x: 'Пятница', y: '18:00', value: 1.25}, {x: 'Суббота', y: '18:00', value: 8.5}, {x: 'Воскресенье', y: '18:00', value: 11.75}, // 20:00 {x: 'Понедельник', y: '20:00', value: 1}, {x: 'Вторник', y: '20:00', value: 1}, {x: 'Среда', y: '20:00', value: 0.5}, {x: 'Четверг', y: '20:00', value: 0}, {x: 'Пятница', y: '20:00', value: 0}, {x: 'Суббота', y: '20:00', value: 11}, {x: 'Воскресенье', y: '20:00', value: 12}, // 22:00 {x: 'Понедельник', y: '22:00', value: 0.25}, {x: 'Вторник', y: '22:00', value: 0}, {x: 'Среда', y: '22:00', value: 0}, {x: 'Четверг', y: '22:00', value: 0.25}, {x: 'Пятница', y: '22:00', value: 1}, {x: 'Суббота', y: '22:00', value: 9.75}, {x: 'Воскресенье', y: '22:00', value: 15.75} ] }; // Создаем тепловую карту для пункта пропуска "Брест" (автобусы) addCheckpointData('heatmap-container-2', 'Брест (автобусы)', brestBusData); // Данные для пункта пропуска "Каменный Лог" const kamLlogData = { xLabels: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'], yLabels: ['0:00', '2:00', '4:00', '6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'], values: [ // 0:00 {x: 'Понедельник', y: '0:00', value: 22.5}, {x: 'Вторник', y: '0:00', value: 7.5}, {x: 'Среда', y: '0:00', value: 0}, {x: 'Четверг', y: '0:00', value: 22.5}, {x: 'Пятница', y: '0:00', value: 25}, {x: 'Суббота', y: '0:00', value: 0}, {x: 'Воскресенье', y: '0:00', value: 2.5}, // 2:00 {x: 'Понедельник', y: '2:00', value: 12.5}, {x: 'Вторник', y: '2:00', value: 3.75}, {x: 'Среда', y: '2:00', value: 0}, {x: 'Четверг', y: '2:00', value: 20}, {x: 'Пятница', y: '2:00', value: 17.5}, {x: 'Суббота', y: '2:00', value: 0}, {x: 'Воскресенье', y: '2:00', value: 0}, // 4:00 {x: 'Понедельник', y: '4:00', value: 7.5}, {x: 'Вторник', y: '4:00', value: 0}, {x: 'Среда', y: '4:00', value: 0}, {x: 'Четверг', y: '4:00', value: 15}, {x: 'Пятница', y: '4:00', value: 10}, {x: 'Суббота', y: '4:00', value: 0}, {x: 'Воскресенье', y: '4:00', value: 0}, // 6:00 {x: 'Понедельник', y: '6:00', value: 7.5}, {x: 'Вторник', y: '6:00', value: 0}, {x: 'Среда', y: '6:00', value: 0}, {x: 'Четверг', y: '6:00', value: 12.5}, {x: 'Пятница', y: '6:00', value: 5}, {x: 'Суббота', y: '6:00', value: 0}, {x: 'Воскресенье', y: '6:00', value: 0}, // 8:00 {x: 'Понедельник', y: '8:00', value: 10}, {x: 'Вторник', y: '8:00', value: 0}, {x: 'Среда', y: '8:00', value: 0}, {x: 'Четверг', y: '8:00', value: 2.5}, {x: 'Пятница', y: '8:00', value: 7.5}, {x: 'Суббота', y: '8:00', value: 0}, {x: 'Воскресенье', y: '8:00', value: 0}, // 10:00 {x: 'Понедельник', y: '10:00', value: 5}, {x: 'Вторник', y: '10:00', value: 0}, {x: 'Среда', y: '10:00', value: 6.25}, {x: 'Четверг', y: '10:00', value: 7.5}, {x: 'Пятница', y: '10:00', value: 7.5}, {x: 'Суббота', y: '10:00', value: 0}, {x: 'Воскресенье', y: '10:00', value: 0}, // 12:00 {x: 'Понедельник', y: '12:00', value: 10}, {x: 'Вторник', y: '12:00', value: 7.5}, {x: 'Среда', y: '12:00', value: 20}, {x: 'Четверг', y: '12:00', value: 22.5}, {x: 'Пятница', y: '12:00', value: 7.5}, {x: 'Суббота', y: '12:00', value: 0}, {x: 'Воскресенье', y: '12:00', value: 12.5}, // 14:00 {x: 'Понедельник', y: '14:00', value: 15}, {x: 'Вторник', y: '14:00', value: 10}, {x: 'Среда', y: '14:00', value: 22.5}, {x: 'Четверг', y: '14:00', value: 40}, {x: 'Пятница', y: '14:00', value: 7.5}, {x: 'Суббота', y: '14:00', value: 0}, {x: 'Воскресенье', y: '14:00', value: 22.5}, // 16:00 {x: 'Понедельник', y: '16:00', value: 20}, {x: 'Вторник', y: '16:00', value: 15}, {x: 'Среда', y: '16:00', value: 20}, {x: 'Четверг', y: '16:00', value: 50}, {x: 'Пятница', y: '16:00', value: 5}, {x: 'Суббота', y: '16:00', value: 0}, {x: 'Воскресенье', y: '16:00', value: 32.5}, // 18:00 {x: 'Понедельник', y: '18:00', value: 17.5}, {x: 'Вторник', y: '18:00', value: 12.5}, {x: 'Среда', y: '18:00', value: 20}, {x: 'Четверг', y: '18:00', value: 45}, {x: 'Пятница', y: '18:00', value: 7.5}, {x: 'Суббота', y: '18:00', value: 3.75}, {x: 'Воскресенье', y: '18:00', value: 47.5}, // 20:00 {x: 'Понедельник', y: '20:00', value: 12.5}, {x: 'Вторник', y: '20:00', value: 7.5}, {x: 'Среда', y: '20:00', value: 17.5}, {x: 'Четверг', y: '20:00', value: 30}, {x: 'Пятница', y: '20:00', value: 5}, {x: 'Суббота', y: '20:00', value: 2.5}, {x: 'Воскресенье', y: '20:00', value: 50}, // 22:00 {x: 'Понедельник', y: '22:00', value: 10}, {x: 'Вторник', y: '22:00', value: 7.5}, {x: 'Среда', y: '22:00', value: 20}, {x: 'Четверг', y: '22:00', value: 27.5}, {x: 'Пятница', y: '22:00', value: 0}, {x: 'Суббота', y: '22:00', value: 2.5}, {x: 'Воскресенье', y: '22:00', value: 45} ] }; // Создаем тепловую карту для пункта пропуска "Каменный Лог" addCheckpointData('heatmap-container-3', 'Каменный Лог', kamLlogData); // Данные для пункта пропуска "Бенякони" const benyakoniData = { xLabels: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'], yLabels: ['0:00', '2:00', '4:00', '6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00'], values: [ // 0:00 {x: 'Понедельник', y: '0:00', value: 7.5}, {x: 'Вторник', y: '0:00', value: 0}, {x: 'Среда', y: '0:00', value: 0}, {x: 'Четверг', y: '0:00', value: 0}, {x: 'Пятница', y: '0:00', value: 0}, {x: 'Суббота', y: '0:00', value: 0}, {x: 'Воскресенье', y: '0:00', value: 0}, // 2:00 {x: 'Понедельник', y: '2:00', value: 7.5}, {x: 'Вторник', y: '2:00', value: 0}, {x: 'Среда', y: '2:00', value: 0}, {x: 'Четверг', y: '2:00', value: 0}, {x: 'Пятница', y: '2:00', value: 0}, {x: 'Суббота', y: '2:00', value: 0}, {x: 'Воскресенье', y: '2:00', value: 0}, // 4:00 {x: 'Понедельник', y: '4:00', value: 7.5}, {x: 'Вторник', y: '4:00', value: 0}, {x: 'Среда', y: '4:00', value: 0}, {x: 'Четверг', y: '4:00', value: 0}, {x: 'Пятница', y: '4:00', value: 0}, {x: 'Суббота', y: '4:00', value: 0}, {x: 'Воскресенье', y: '4:00', value: 0}, // 6:00 {x: 'Понедельник', y: '6:00', value: 0}, {x: 'Вторник', y: '6:00', value: 0}, {x: 'Среда', y: '6:00', value: 0}, {x: 'Четверг', y: '6:00', value: 0}, {x: 'Пятница', y: '6:00', value: 0}, {x: 'Суббота', y: '6:00', value: 0}, {x: 'Воскресенье', y: '6:00', value: 0}, // 8:00 {x: 'Понедельник', y: '8:00', value: 0}, {x: 'Вторник', y: '8:00', value: 0}, {x: 'Среда', y: '8:00', value: 0}, {x: 'Четверг', y: '8:00', value: 0}, {x: 'Пятница', y: '8:00', value: 0}, {x: 'Суббота', y: '8:00', value: 0}, {x: 'Воскресенье', y: '8:00', value: 0}, // 10:00 {x: 'Понедельник', y: '10:00', value: 0}, {x: 'Вторник', y: '10:00', value: 0}, {x: 'Среда', y: '10:00', value: 0}, {x: 'Четверг', y: '10:00', value: 0}, {x: 'Пятница', y: '10:00', value: 0}, {x: 'Суббота', y: '10:00', value: 0}, {x: 'Воскресенье', y: '10:00', value: 0}, // 12:00 {x: 'Понедельник', y: '12:00', value: 0}, {x: 'Вторник', y: '12:00', value: 0}, {x: 'Среда', y: '12:00', value: 0}, {x: 'Четверг', y: '12:00', value: 2.5}, {x: 'Пятница', y: '12:00', value: 0}, {x: 'Суббота', y: '12:00', value: 0}, {x: 'Воскресенье', y: '12:00', value: 0}, // 14:00 {x: 'Понедельник', y: '14:00', value: 0}, {x: 'Вторник', y: '14:00', value: 0}, {x: 'Среда', y: '14:00', value: 0}, {x: 'Четверг', y: '14:00', value: 10}, {x: 'Пятница', y: '14:00', value: 0}, {x: 'Суббота', y: '14:00', value: 0}, {x: 'Воскресенье', y: '14:00', value: 3.75}, // 16:00 {x: 'Понедельник', y: '16:00', value: 5}, {x: 'Вторник', y: '16:00', value: 0}, {x: 'Среда', y: '16:00', value: 0}, {x: 'Четверг', y: '16:00', value: 15}, {x: 'Пятница', y: '16:00', value: 0}, {x: 'Суббота', y: '16:00', value: 0}, {x: 'Воскресенье', y: '16:00', value: 12.5}, // 18:00 {x: 'Понедельник', y: '18:00', value: 2.5}, {x: 'Вторник', y: '18:00', value: 0}, {x: 'Среда', y: '18:00', value: 0}, {x: 'Четверг', y: '18:00', value: 12.5}, {x: 'Пятница', y: '18:00', value: 0}, {x: 'Суббота', y: '18:00', value: 0}, {x: 'Воскресенье', y: '18:00', value: 22.5}, // 20:00 {x: 'Понедельник', y: '20:00', value: 2.5}, {x: 'Вторник', y: '20:00', value: 0}, {x: 'Среда', y: '20:00', value: 0}, {x: 'Четверг', y: '20:00', value: 10}, {x: 'Пятница', y: '20:00', value: 0}, {x: 'Суббота', y: '20:00', value: 0}, {x: 'Воскресенье', y: '20:00', value: 22.5}, // 22:00 {x: 'Понедельник', y: '22:00', value: 0}, {x: 'Вторник', y: '22:00', value: 6.25}, {x: 'Среда', y: '22:00', value: 0}, {x: 'Четверг', y: '22:00', value: 7.5}, {x: 'Пятница', y: '22:00', value: 0}, {x: 'Суббота', y: '22:00', value: 0}, {x: 'Воскресенье', y: '22:00', value: 25} ] }; // Создаем тепловую карту для пункта пропуска "Бенякони" addCheckpointData('heatmap-container-4', 'Бенякони', benyakoniData); document.addEventListener('DOMContentLoaded', function() { createLineChart('linechart-container', brestLineData, { title: 'Динамика очередей в пункте пропуска «Брест» (февраль-март 2025 г.)', lineColor: '#2a5a8a', tooltipFormat: (d) => { const dateFormat = new Intl.DateTimeFormat('ru', { day: '2-digit', month: '2-digit', year: 'numeric' }); const timeFormat = new Intl.DateTimeFormat('ru', { hour: '2-digit', minute: '2-digit' }); return `Дата: ${dateFormat.format(d.date)}

Время: ${timeFormat.format(d.date)}

В очереди: ${d.count} авто`; } }); createHeatmap('heatmap-container-1', brestData, { title: 'Тепловая карта очередей в пункте пропуска «Брест»' }); createHeatmap('heatmap-container-2', brestBusData, { title: 'Тепловая карта очередей в пункте пропуска «Брест» (автобусы)' }); createHeatmap('heatmap-container-3', kamLlogData, { title: 'Тепловая карта очередей в пункте пропуска «Каменный Лог»' }); createHeatmap('heatmap-container-4', benyakoniData, { title: 'Тепловая карта очередей в пункте пропуска «Бенякони»' }); });