{
    "version": "https:\/\/jsonfeed.org\/version\/1.1",
    "title": "Коломенский трамвай",
    "_rss_description": "Комментарии разработчиков о создании сайта Коломенских трамваев.",
    "_rss_language": "ru",
    "_itunes_email": "mailbox@kolomna-trams.ru",
    "_itunes_categories_xml": "",
    "_itunes_image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/userpic\/userpic-square@2x.jpg?1773845294",
    "_itunes_explicit": "no",
    "home_page_url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/",
    "feed_url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/rss\/",
    "icon": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/userpic\/userpic@2x.jpg?1773845294",
    "authors": [
        {
            "name": "kolomna-trams",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/",
            "avatar": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/userpic\/userpic@2x.jpg?1773845294"
        }
    ],
    "items": [
        {
            "id": "20",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/navigation-at-route-page-p1\/",
            "title": "Навигация на странице «Маршрут». Часть 1",
            "content_html": "<p>Страница «Маршрут» — единственная, которая имеет две шапки вверху сайта.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-7.png\" width=\"2372\" height=\"1554\" alt=\"\" \/>\n<\/div>\n<p>Вторая навигация позволяет перемещаться по разным «вкладкам» этой страницы. При этом всплывающее окно в правой части (или внизу на мобильных устройствах) не сбрасывается при переходе между вкладками. Например, вы можете выбрать остановку в алфавитном списке на вкладке «Остановки», а затем проложить маршрут до другой остановки, найдя её на схеме.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-04-28-at-20.22.56.gif\" width=\"2202\" height=\"1432\" alt=\"\" \/>\n<\/div>\n<p>В далеком 2022 году реализация этой фичи была чисто джаваскриптовая: кнопки в навигации вызывали метод <b>switch_tab(tab)<\/b>, в аргумент которой передавалась нужная вкладка. HTML-страница включала 4 div-блока, и функция просто показывала один нужный блок и прятала остальные три. URL при этом не менялся: <a href=\"https:\/\/kolomna-trams.ru\/route\/\">https:\/\/kolomna-trams.ru\/route\/<\/a><\/p>\n<pre class=\"e2-text-code\"><code class=\"\">function switch_tab(tab) {\n    if (tab == &quot;&quot;) {\n        tab = &quot;map&quot;;\n    }\n\n    document.getElementById(&#039;content-lines&#039;).style.display = &#039;none&#039;;\n    document.getElementById(&#039;content-stops&#039;).style.display = &#039;none&#039;;\n    document.getElementById(&#039;content-visit&#039;).style.display = &#039;none&#039;;\n    document.getElementById(&#039;content-map&#039;).style.display = &#039;none&#039;;\n\n    document.getElementById(&#039;content-&#039; + tab).style.display = &#039;block&#039;;\n}\n\nswitch_tab(&quot;map&quot;);<\/code><\/pre><p>О том, что это чудовищный костыль и так делать не нужно, мы догадались почти сразу. На каком-то из сайтов мы обнаружили использование хэшей (#...) для навигации. Оказалось, что JavaScript умеет отлавливать событие изменения хэша страницы и выполнять любое действие. Теперь сайт стал лучше: кнопки в навигации стали вполне себе ссылками, содержащими хэш:<\/p>\n<ul>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/#lines\">https:\/\/kolomna-trams.ru\/route\/#lines<\/a> — маршруты<\/li>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/#stops\">https:\/\/kolomna-trams.ru\/route\/#stops<\/a> — остановки<\/li>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/#visit\">https:\/\/kolomna-trams.ru\/route\/#visit<\/a> — места<\/li>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/#map\">https:\/\/kolomna-trams.ru\/route\/#map<\/a> — схема<\/li>\n<\/ul>\n<p>Если никакого хэша нет, то сайт считает, что нужно показать схему. А джаваскриптовый код переехал из обработчика события нажатия на кнопку в обработчик события смены хэша.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">function switch_tab() {\n    let tab = window.location.hash;\n    tab = tab.substring(1);\n    if (tab == &quot;&quot;) {\n        tab = &quot;scheme&quot;;\n    }\n\n    document.getElementById(&#039;content-lines&#039;).style.display = &#039;none&#039;;\n    document.getElementById(&#039;content-stops&#039;).style.display = &#039;none&#039;;\n    document.getElementById(&#039;content-visit&#039;).style.display = &#039;none&#039;;\n    document.getElementById(&#039;content-map&#039;).style.display = &#039;none&#039;;\n\n    document.getElementById(&#039;content-&#039; + tab).style.display = &#039;block&#039;;\n}\n\nswitch_tab();\nwindow.addEventListener(&#039;hashchange&#039;, switch_tab);<\/code><\/pre><p>Открылся дополнительный плюс этого метода — теперь у каждой вкладки появился уникальный URL, а значит и способ поделиться. К примеру, если ваш друг спрашивает, где можно посмотреть список остановок Коломенского трамвая, вы отправляете ему: <a href=\"https:\/\/kolomna-trams.ru\/route\/#stops,\">https:\/\/kolomna-trams.ru\/route\/#stops,<\/a> и нужная вкладка сама открывается у него на устройстве.<\/p>\n<p>Увы, но такой способ имел большой недостаток. Технически, эти 4 вкладки были одной веб-страницей, и поисковиками индексировались как одна страница — а значит, открывалась она всегда на вкладке по умолчанию (на вкладке со схемой). И даже если условный Google смог сообразить, что на этой странице содержится информация об остановках трамваев, то если пользователь кликнет на ссылку из поисковой выдачи, он увидит:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/navigation-at-route-page.png\" width=\"2426\" height=\"1656\" alt=\"\" \/>\n<\/div>\n<p>А должен увидеть это:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/navigation-at-route-page-1.png\" width=\"2426\" height=\"1656\" alt=\"\" \/>\n<\/div>\n<p>Встала непростая задача. Нам нужно сделать так, чтобы четыре разные вкладки являлись разными веб-страницами (а значит, имели разные URL-адреса), при этом переход по ним не являлся переходом в прямом смысле этого слова (не перезагружал страницу).<\/p>\n<p>Оказалось, что этому есть решение. Во-первых, мы переселили все вкладки на разные страницы:<\/p>\n<ul>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/lines\/\">https:\/\/kolomna-trams.ru\/route\/lines\/<\/a> — маршруты<\/li>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/stops\/\">https:\/\/kolomna-trams.ru\/route\/stops\/<\/a> — остановки<\/li>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/visit\/\">https:\/\/kolomna-trams.ru\/route\/visit\/<\/a> — места<\/li>\n<li><a href=\"https:\/\/kolomna-trams.ru\/route\/map\/\">https:\/\/kolomna-trams.ru\/route\/map\/<\/a> — схема<\/li>\n<\/ul>\n<p>Во-вторых, сделали кнопки в навигации настоящими ссылками на эти страницы. То есть на них можно даже нажать правой кнопкой и выбрать «Открыть в новой вкладке». А на маке ещё и так можно сделать:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/navigaciya-na-stranice-marshruty.png\" width=\"2288\" height=\"1534\" alt=\"\" \/>\n<\/div>\n<p>А главный фокус состоит в следующем. При нажатии на кнопку JavaScript перехватывает нажатие и запрещает прямой переход по ссылке. Вместо этого он загружает содержание страницы себе во внутреннюю переменную, достает оттуда контент вкладки (то есть то, что под шапкой, — саму шапку, а также подвал, обновлять не надо) и заменяет её прямо на текущей странице.<\/p>\n<pre class=\"e2-text-code\"><code class=\"\">function set_up_buttons() {\n    var links = document.getElementsByClassName(&#039;trams-v3-subnav-link&#039;);\n    for (let i = 0; i &lt; links.length; i++) {\n        const link_url = links[i].getAttribute(&#039;href&#039;);\n        links[i].addEventListener(&quot;click&quot;, (event) =&gt; {\n            event.preventDefault();\n            switch_tab(link_url);\n        });\n    }\n}\n\nfunction switch_tab(url) {\n    var xhttp = new XMLHttpRequest();\n    xhttp.onreadystatechange = function() {\n        if (this.readyState == 4 &amp;&amp; this.status == 200) {\n\t    build_page(this.responseText, url);\n\t    window.history.replaceState(null, null, url + window.location.hash);\n\t}\n    };\n    xhttp.open(&#039;GET&#039;, &#039;https:\/\/&#039; + window.location.hostname + url);\n    xhttp.send();\n}\n\nset_up_buttons();<\/code><\/pre><p>А если у пользователя по какой-то причине отключен JavaScript или скрипт просто не подгрузился — ничего страшного, кнопки будут работать как обычные ссылки. Да, страница всё же будет перезагружаться и «магия» пропадёт, но зато человек сможет пользоваться сайтом, а не останется с нерабочим «кирпичом».<\/p>\n",
            "summary": "Страница «Маршрут» — единственная, которая имеет две шапки вверху сайта",
            "date_published": "2026-04-28T20:50:30+03:00",
            "date_modified": "2026-04-29T18:45:50+03:00",
            "tags": [
                "архитектура",
                "код",
                "фронтенд"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-7.png",
            "_date_published_rfc2822": "Tue, 28 Apr 2026 20:50:30 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "20",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": true,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-7.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-04-28-at-20.22.56.gif",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/navigation-at-route-page.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/navigation-at-route-page-1.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/navigaciya-na-stranice-marshruty.png"
                ]
            }
        },
        {
            "id": "10",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/crowd-predict-people-counting\/",
            "title": "Прогнозирование загруженности: считаем людей",
            "content_html": "<p>Чтобы модели было на чём обучаться, нужно собрать данные о загруженности. Данные должны быть в таком формате:<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>Маршрут<\/b><\/td>\n<td><b>Остановка<\/b><\/td>\n<td><b>Вошло<\/b><\/td>\n<td><b>Вышло<\/b><\/td>\n<td><b>В трамвае<\/b><\/td>\n<td><b>Время<\/b><\/td>\n<td><b>Другие данные...<\/b><\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>Сад дворца<\/td>\n<td>4<\/td>\n<td>2<\/td>\n<td>16<\/td>\n<td>15:43<\/td>\n<td>...<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>Дворец культуры<\/td>\n<td>7<\/td>\n<td>3<\/td>\n<td>20<\/td>\n<td>15:45<\/td>\n<td>...<\/td>\n<\/tr>\n<\/table>\n<p>Как бы собрать такие данные?.. Оказывается, до нас умные люди <a href=\"https:\/\/s.esrae.ru\/auts\/pdf\/2014\/3\/206.pdf\">уже задавались этим вопросом<\/a>, и вот какие способы они придумали.<\/p>\n<p>Во-первых, способы делятся по длительности охватываемого периода различают:<\/p>\n<ul>\n<li><b>систематическое обследование<\/b> — регулярные исследования<\/li>\n<li><b>разовое обследование<\/b> — кратковременные обследования для выявления конкретных результатов (для более точных результатов)<\/li>\n<\/ul>\n<p>В нашем исследовании используются оба типа: разовые обследования для сбора первоначальных данных и систематические — для поддержания алгоритма в актуальном состоянии.<\/p>\n<p>Во-вторых, по ширине охвата транспортной сети различают:<\/p>\n<ul>\n<li><b>сплошные обследования<\/b> проводят одновременно на всей транспортной сети обслуживаемого населенного пункта. По результатам обследования решают вопросы функционирования транспортной сети, такие как направление ее развития, координация работы различных видов транспорта в соответствии с мощностью пассажирских потоков;<\/li>\n<li><b>выборочные обследования<\/b> проводят по отдельным районам движения, конфликтным точкам для решения локальных задач.<\/li>\n<\/ul>\n<p>В нашем исследовании в основном используются сплошные обследования.<\/p>\n<p>Ну и дальше самое интересное — виды обследования.<\/p>\n<p><b>Анкетное исследование<\/b><br \/>\nЕго суть в том, чтобы опрашивать людей об их перемещениях. Опрашивать можно по-разному: в трамваях, на остановках, в интернете, по телефону, в школах, университетах и на работе.<\/p>\n<p>Очевидный плюс — можно собрать намного больше информации, чем любыми другими методами, поскольку мы напрямую спрашиваем людей. Спросить можно о разном:<\/p>\n<ul>\n<li>цель поездки<\/li>\n<li>возраст пассажира<\/li>\n<li>род занятий пассажира (школьник, студент, работающий, безработный)<\/li>\n<li>где проживает<\/li>\n<li>где учится или работает<\/li>\n<\/ul>\n<p>Минусом здесь является то, что нам необходимо спрашивать людей, а далеко не у всех есть время (и желание) отвечать на эти вопросы. Много информации так не наскребешь, и сведения получатся неполные.<\/p>\n<p><b>Глазомерное исследование<\/b><br \/>\nЭтот метод предполагает, что на каждой остановке водитель, кондуктор или учетчик заполняет поле в соответствующей форме, а именно — ему нужно проставить значение от 1 до 5, оценив заполненность салона по следующей схеме.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>Зн.<\/b><\/td>\n<td><b>Заполненность<\/b><\/td>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>Заняты до половины мест для сидения<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>Заняты в основном все места для сидения<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>Заняты все места для сидения и до половины мест для проезда стоя<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>Трамвай заполнен полностью, но посадка ещё возможна<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>Трамвай переполнен, наблюдаются отказы в посадке<\/td>\n<\/tr>\n<\/table>\n<p>Этот метод очень простой и быстрый, однако информации лишь об уровне заполненности, а не о количестве пассажиров может не хватать для точных исследований. При этом этот метод легче встроить в бизнес-процесс, ведь водителю очень просто оценить заполненность трамвая и нажать одну из пяти кнопок на планшете.<\/p>\n<p><b>Весовой метод<\/b><br \/>\nДанный метод предписывает смонтировать на пневморессорах трамвая датчики, определяющие примерный вес салона. Вес можно сконвертировать в загруженность или даже в количество пассажиров (обычно среднюю массу одного пассажира берут за 70 кг). Недостатка у такого подхода два: во-первых, нужно монтировать эти датчики, а во-вторых, нет возможности вычислить, сколько человек вошло и вышло. Ну и точность, конечно, не ахти.<\/p>\n<p><b>Табличный метод<\/b><br \/>\nМетод «в лоб». В трамваях (как правило, у дверей или на накопительной площадке сзади) располагаются учетчики, которые считают число вошедших и вышедших пассажиров, затем записывают их в таблицу. Этот метод самый точный и позволяет определить всю минимально необходимую информацию без влияния на пассажиров. Недостаток здесь очевиден — работа учетчиков не бесплатна, да и на все-все рейсы их не напасешься. Кроме того, всё же хочется как-то автоматизировать этот процесс.<\/p>\n<p><b>Опросный метод<\/b><br \/>\nПохож на табличный, но здесь учетчики не просто считают пассажиров, а ещё подходят и спрашивают, куда кто едет, где совершает пересадку и на каких маршрутах. Этот метод желательно применять там, где число пассажиров не очень велико, ведь иначе пассажирообмен на остановках может очень замедлиться.<\/p>\n<p><b>Талонный метод<\/b><br \/>\nА вот здесь уже поинтереснее. Каждому пассажиру при посадке вручают специальный талон, который он должен сдавать учетчику при выходе из трамвая. Всё устроено так, что по талонам потом можно понять, сколько человек откуда и куда ехали. К примеру, нумерация талонов соответствует маршруту и остановке входа в трамвай, а для сортировки талонов по останове выхода используют разные стопки или «прокладки» внутри одной стопки.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/IMG_6534.jpeg.jpg\" width=\"2425\" height=\"2560\" alt=\"\" \/>\n<\/div>\n<p>Этот метод всегда является временным, так как пассажиры не то чтобы очень рады на постоянной основе участвовать в таких экспериментах.<\/p>\n<p><b>Отчётно-статистический метод<\/b><br \/>\nЭтот метод предлагает считать пассажиров косвенными методами — например, по количеству проданных билетов. Этот способ хорош своей легковесностью (билеты всё равно ведь продавать), а ещё с его помощью можно получить данные за прошлый период, ещё до того, как наше исследование начало проводиться. Но ничего, помимо числа людей, вошедших на каждой остановке, этот метод нам предоставить не может. Более того, если на какой-то из остановок вошло очень много людей, то кондуктор может не успеть продать всем билеты, пока трамвай ещё не доехал до следующей остановки, и тогда некоторые из пассажиров попадут в учет следующей остановки. Наконец, не стоит забывать о том, что некоторые пассажиры пытаются проехать без билета (это особенно актуально для трамваев, где вместо кондуктора используются валидаторы), что влияет на точность сбора данных.<\/p>\n<p><b>Автоматизированные методы<\/b><br \/>\nЭто группа методов, посвященная сбору данных через автоматизированные устройства — датчики прохода в дверях, контактные ступеньки, камеры с искусственным интеллектом. Все их объединяет низкая точность в сборе данных: низкий пассажир может спрятаться от камеры, пара быстрых пассажиров считаются за одного, некоторые стоят в дверях и мешают работе датчиков.<\/p>\n<p>Чтобы собрать основную «базу» о загруженности, мы использовали табличный метод. Сначала мы подготовили базу данных для этого.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/crowd-predict-people-counting.png\" width=\"1470\" height=\"968\" alt=\"\" \/>\n<\/div>\n<p>Вначале (перед поездкой) исследователь регистрирует свою поездку, указывая:<\/p>\n<ul>\n<li>номер маршрута<\/li>\n<li>модель трамвая (от неё зависит низкопольность и число мест)<\/li>\n<li>дату поездки<\/li>\n<li>информацию о погоде (силу дождя или снега, скорость ветра, температуру, есть ли гроза и туман)<\/li>\n<\/ul>\n<p>Затем на каждой остановке исследователь заносит информацию о числе вошедших и вышедших пассажиров, и добавляет временную метку.<\/p>\n<p>Собранные данные можно посмотреть <a href=\"https:\/\/github.com\/kolomna-trams\/open-data\/blob\/main\/crowd\/crowd_raw.csv\">на нашем GitHub.<\/a><\/p>\n",
            "summary": "Чтобы модели было на чём обучаться, нужно собрать данные о загруженности. Как бы собрать такие данные?.. Оказывается, до нас умные люди уже задавались этим вопросом, и вот какие способы они придумали.",
            "date_published": "2026-04-25T12:41:02+03:00",
            "date_modified": "2026-04-25T12:42:26+03:00",
            "tags": [
                "аналитика данных",
                "машинное обучение",
                "прогнозирование загруженности"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/IMG_6534.jpeg.jpg",
            "_date_published_rfc2822": "Sat, 25 Apr 2026 12:41:02 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "10",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": true,
                "links_required": [],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/IMG_6534.jpeg.jpg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/crowd-predict-people-counting.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/crowd-predict.png"
                ]
            }
        },
        {
            "id": "22",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/preprint-optimizing\/",
            "title": "Вышла статья «Оптимизация сети маршрутов трамваев методами искусственного интеллекта»",
            "content_html": "<p>Вышла статья «Оптимизация сети маршрутов трамваев методами искусственного интеллекта» в Институте прикладной математики им. М.В. Келдыша Российской академии наук.<\/p>\n<p>Написали статью разработчик и автор проекта Дмитрий Балабанов и его научный сотрудник Владимир Судаков.<\/p>\n<p>Статья посвящена оптимизации маршрутной сети трамваев на примере города Коломны с использованием методов искусственного интеллекта. Мы формализовали существующую трамвайную сеть как ориентированный граф, ввели понятие «комфорта пассажира» (через время ожидания, переполненность и число пересадок), выведенное на основе опроса и логистической регрессии. Задача сводится к распределению 40 трамвайных вагонов по возможным маршрутам (всего их 55) так, чтобы максимизировать суммарный комфорт. Из-за комбинаторной сложности (≈10¹¹ вариантов) мы применяем семь методов оптимизации: жадный алгоритм, генерацию столбцов, перебор пар маршрутов, генетический алгоритм, соревнование агентов, кооперацию агентов и имитацию отжига.<\/p>\n<p>Подробнее о проекте можно узнать здесь в блоге по тегу <a href=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/tags\/optimizing\/\">«оптимизация трамвайной сети».<\/a><\/p>\n<p>Почитать о статье можно здесь.<br \/>\n<a href=\"https:\/\/library.keldysh.ru\/preprint.asp?id=2026-14\">https:\/\/library.keldysh.ru\/preprint.asp?id=2026-14<\/a><\/p>\n<p>А саму статью (бесплатно) — здесь.<br \/>\n<a href=\"https:\/\/keldysh.ru\/papers\/2026\/prep2026_14.pdf\">https:\/\/keldysh.ru\/papers\/2026\/prep2026_14.pdf<\/a><\/p>\n",
            "summary": "Вышла статья «Оптимизация сети маршрутов трамваев методами искусственного интеллекта» в Институте прикладной математики им",
            "date_published": "2026-04-19T21:00:00+03:00",
            "date_modified": "2026-04-28T17:27:36+03:00",
            "tags": [
                "аналитика данных",
                "ИМП им. Келдыша",
                "маршруты",
                "машинное обучение",
                "оптимизация трамвайной сети",
                "статья"
            ],
            "_date_published_rfc2822": "Sun, 19 Apr 2026 21:00:00 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "22",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": []
            }
        },
        {
            "id": "4",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/tariffs-history\/",
            "title": "Стоимость проезда с 1948 по 2026",
            "content_html": "<p>Если перейти по ссылке:<\/p>\n<blockquote>\n<p><a href=\"https:\/\/kolomna-trams.ru\/workshop\/wayback\/museum\/2007\/\">https:\/\/kolomna-trams.ru\/workshop\/wayback\/museum\/2007\/<\/a><\/p>\n<\/blockquote>\n<p>то вы увидите, что в 2007 году проезд в трамвае стоил 12 рублей. Можете попробовать любой другой год, просто поменяв число в URL — всё работает.<\/p>\n<p>Открытых данных по стоимости проезда в одном месте нигде не было, поэтому пришлось искать эту информацию в разных источниках.<\/p>\n<p>В 2026 году (на момент публикации заметки) в Коломне действуют 6 разных тарифов:<\/p>\n<ol start=\"1\">\n<li>Оплата банковской картой. Стабильно 73 рубля<\/li>\n<li>Оплата картами «Стрелка» и «Тройка». 73 рубля, но каждые 10 поездок стоимость снижается на 7%, с 51-й поездки снижаться перестает<\/li>\n<li>Оплата ученической «Стрелкой» (для школьников и студентов). Скидка 50% с 1-й по 35-ю поездку и 99% с 36-й поездки<\/li>\n<li>Оплата льготной «Стрелкой» (для ветеранов). Скидка 50%<\/li>\n<li>Оплата (если можно так назвать) картой пенсионера, скидка 100% (бесплатный проезд)<\/li>\n<li>Дети до 7 лет могут ехать бесплатно<\/li>\n<\/ol>\n<p>Эту информацию мы узнали из <a href=\"https:\/\/kolomna-spravka.ru\/novosti\/s-1-yanvarya-proezd-v-obschestvennom-transporte-podorozhaet.\">https:\/\/kolomna-spravka.ru\/novosti\/s-1-yanvarya-proezd-v-obschestvennom-transporte-podorozhaet.<\/a> Вообще так делать нехорошо: «Коломна Справка» — это просто новостной портал, а официальные тарифы устанавливаются постановлением правительства <a href=\"https:\/\/mosreg.ru\/download\/document\/1341676\" class=\"nu\">«<u>Об утверждении регулируемых тарифов на перевозку пассажиров и багажа автомобильным транспортом и городским наземным электрическим транспортом...<\/u>»<\/a> и правильнее бы ссылаться на этот документ. Но, забегая вперед, чем дальше в прошлое мы идём, тем сложнее искать информацию, поэтому будем считать, что новостные агрегаторы правильно печатают тарифы.<\/p>\n<p>Кстати, чтобы эта страница не стала в будущем грустным кладбищем истории с неработающими ссылками, мы на всякий случай заархивировали все ссылки на этой странице. Если что-то не работает — открывайте дамп на веб-архиве.<\/p>\n<p>Схема оплаты «банковская карта + Стрелка + Тройка» будет с нами ещё долго, и информация в основном будет открытой и находиться по первой ссылке в Google.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>карта<\/b><\/td>\n<td><b>Стрелка\/Тройка<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2026<\/td>\n<td>73 руб<\/td>\n<td>73 руб<\/td>\n<td><a href=\"https:\/\/kolomna-spravka.ru\/novosti\/s-1-yanvarya-proezd-v-obschestvennom-transporte-podorozhaet\">Коломна-Справка<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20260322133258\/https:\/\/kolomna-spravka.ru\/novosti\/s-1-yanvarya-proezd-v-obschestvennom-transporte-podorozhaet\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 июня 2025<\/td>\n<td>64 руб<\/td>\n<td>63 руб<\/td>\n<td><a href=\"https:\/\/msk1.ru\/text\/transport\/2025\/06\/01\/75527081\/\">Мск1<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20250615021721\/https:\/\/msk1.ru\/text\/transport\/2025\/06\/01\/75527081\/\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2025<\/td>\n<td>60 руб<\/td>\n<td>59 руб<\/td>\n<td><a href=\"https:\/\/msk1.ru\/text\/transport\/2025\/01\/02\/74945993\/\">Мск1<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20251214064710\/https:\/\/msk1.ru\/text\/transport\/2025\/01\/02\/74945993\/\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>20 мая 2024<\/td>\n<td>54 руб<\/td>\n<td>54 руб<\/td>\n<td><a href=\"https:\/\/www.interfax-russia.ru\/index.php\/center\/novosti-podmoskovya\/stoimost-proezda-v-obshchestvennom-transporte-menyaetsya-v-podmoskove-s-ponedelnika\">Интерфакс<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20251211180331\/https:\/\/www.interfax-russia.ru\/index.php\/center\/novosti-podmoskovya\/stoimost-proezda-v-obshchestvennom-transporte-menyaetsya-v-podmoskove-s-ponedelnika\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 ноя 2023<\/td>\n<td>50 руб<\/td>\n<td>49,47 руб<\/td>\n<td><a href=\"https:\/\/ramnews.ru\/1-nojabrja-povysjatsja-ceny-na-proezd-v-obshhestvennom-transporte-podmoskovja\/\">РамМедиа<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20231107185208\/https:\/\/ramnews.ru\/1-nojabrja-povysjatsja-ceny-na-proezd-v-obshhestvennom-transporte-podmoskovja\/\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2023<\/td>\n<td>45 руб<\/td>\n<td>44,97 руб<\/td>\n<td><a href=\"https:\/\/abnews.ru\/news\/mosreg\/2023\/1\/2\/stoimost-proezda-v-transporte-podmoskovya-uvelichilas-s-1-yanvarya\">АБН24<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20260328134715\/https:\/\/abnews.ru\/news\/mosreg\/2023\/1\/2\/stoimost-proezda-v-transporte-podmoskovya-uvelichilas-s-1-yanvarya\">архив<\/a><\/td>\n<\/tr>\n<\/table>\n<p>Предыдущее изменение тарифов было 1 января 2022, но в этом промежутке случилось ещё одно событие — в общественном транспорте Подмосковья перестали принимать наличные. Случилось это 18 июня.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tariffs-history.png\" width=\"980\" height=\"1382\" alt=\"\" \/>\n<\/div>\n<p>Как сообщает <a href=\"https:\/\/korolev.bezformata.com\/listnews\/stoimost-proezda-v-obshestvennom\/101148653\/\">источник «Королёв. Без формата»<\/a>, до отмены проезд за наличные стоил 64 рубля — гораздо дороже, чем по карте. Теперь в таблицу добавляем ещё одну колонку — стоимость за наличные.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>наличные<\/b><\/td>\n<td><b>карта<\/b><\/td>\n<td><b>Стрелка\/Тройка<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>18 июня 2022<\/td>\n<td>—<\/td>\n<td>41 руб<\/td>\n<td>40,41 руб<\/td>\n<td><a href=\"https:\/\/odin.ru\/news\/?id=66705\">Одинцовский ГО<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20251119105812\/https:\/\/odin.ru\/news\/?id=66705\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2022<\/td>\n<td>64 руб<\/td>\n<td>41 руб<\/td>\n<td>40,41 руб<\/td>\n<td><a href=\"https:\/\/mosreg.ru\/sobytiya\/novosti\/organy\/komitet-po-tarifam-i-cenam\/stoimost-proezda-v-obshhestvennom-transporte-izmenilas-v-podmoskove\">Правительство МО<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20220101141310\/https:\/\/mosreg.ru\/sobytiya\/novosti\/organy\/komitet-po-tarifam-i-cenam\/stoimost-proezda-v-obshhestvennom-transporte-izmenilas-v-podmoskove\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 фев 2021<\/td>\n<td>58 руб<\/td>\n<td>37 руб<\/td>\n<td>36,74 руб<\/td>\n<td><a href=\"https:\/\/myseldon.com\/ru\/news\/index\/243066181\">Селдон Ньюс<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20260328144016\/https:\/\/myseldon.com\/ru\/news\/index\/243066181\">архив<\/a><\/td>\n<\/tr>\n<\/table>\n<p>Здесь опять стоит прерваться. С 1 февраля 2021 в общественном транспорте Подмосковья стали принимать карту «Тройка». Соответственно, до этого оплата по неё не принималась. Источник — <a href=\"https:\/\/adm-pushkino.ru\/article\/s-1-fevralya-proezd-na-avtobusah-regiona-mozhno-budet-oplatit-kartoj-trojka-331221\">Администрация Пушкина<\/a>.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>наличные<\/b><\/td>\n<td><b>карта<\/b><\/td>\n<td><b>Стрелка<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2021<\/td>\n<td>58 руб<\/td>\n<td>37 руб<\/td>\n<td>36,74 руб<\/td>\n<td><a href=\"https:\/\/myseldon.com\/ru\/news\/index\/243066181\">Селдон Ньюс<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20260328144016\/https:\/\/myseldon.com\/ru\/news\/index\/243066181\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>3 июня 2020<\/td>\n<td>56 руб<\/td>\n<td>36 руб<\/td>\n<td>35,46 руб<\/td>\n<td><a href=\"https:\/\/mir24.tv\/news\/16412234\/v-podmoskove-s-3-iyunya-v-obshchestvennom-transporte-vozobnovitsya-oplata-bankovskimi-kartami\">Мир24<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20260328150029\/https:\/\/mestnievesti.ru\/news\/k-svedeniyu-podolchan-s-3-iyunya-mozhno-budet-oplatit-proezd-bankovskoj-kartoj-v-moskovskoj-oblasti\/\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>22 апр 2020<\/td>\n<td>—<\/td>\n<td>—<\/td>\n<td>35,46 руб<\/td>\n<td><a href=\"https:\/\/normativ.kontur.ru\/document?moduleId=3&documentId=93395\">Контур<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20260328145414\/https:\/\/normativ.kontur.ru\/document?moduleId=3&documentId=93395\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2020<\/td>\n<td>56 руб<\/td>\n<td>36 руб<\/td>\n<td>35,46 руб<\/td>\n<td><a href=\"https:\/\/mosreg.ru\/sobytiya\/novosti\/organy\/komitet-po-tarifam-i-cenam\/stoimost-proezda-v-obshchestvennom-transporte-podmoskovya-vyrastet-na-3-v-2020-godu\">Мосрег<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20210603203908\/https:\/\/mosreg.ru\/sobytiya\/novosti\/organy\/komitet-po-tarifam-i-cenam\/stoimost-proezda-v-obshchestvennom-transporte-podmoskovya-vyrastet-na-3-v-2020-godu\">архив<\/a><\/td>\n<\/tr>\n<\/table>\n<p>С 22 апреля по 3 июня 2020, во время пандемии COVID-19, оплачивать проезд можно было только по социальной карте или по транспортной карте «Стрелка», поскольку к ним можно было привязать цифровой пропуск. Проезд за наличные был запрещен из-за того, что купюры и монеты легко передают инфекцию.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>наличные<\/b><\/td>\n<td><b>карта<\/b><\/td>\n<td><b>Стрелка<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2019<\/td>\n<td>53 руб<\/td>\n<td>34,43 руб<\/td>\n<td>34,43 руб<\/td>\n<td><a href=\"https:\/\/rg.ru\/2018\/12\/29\/reg-cfo\/v-podmoskove-podorozhaet-proezd-na-obshchestvennom-transporte.html\">Российская газета<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20250713222332\/https:\/\/rg.ru\/2018\/12\/29\/reg-cfo\/v-podmoskove-podorozhaet-proezd-na-obshchestvennom-transporte.html\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 мар 2018<\/td>\n<td>48 руб<\/td>\n<td>32,92 руб<\/td>\n<td>32,92 руб<\/td>\n<td><a href=\"https:\/\/zelenograd-news.ru\/news\/economics\/proezd_na_gorodskom_transporte_v_podmoskove_podorozhal_\">Зеленоград сегодня<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20220117170524\/https:\/\/mosreg.ru\/sobytiya\/novosti\/news-submoscow\/tarify-na-proezd-v-obschestvennom-transporte-podmoskovya-ne-prevysyat-4-v-2018-g-6198\">архив<\/a><\/td>\n<\/tr>\n<\/table>\n<p>1 марта 2018 года — первый день, когда начали принимать банковские карты для оплаты проезда. До этого можно было оплатить либо наличными, либо картой «Стрелка». Источник — <a href=\"https:\/\/mosreg.ru\/sobytiya\/infografika\/beskontaktnaya-oplata-proezda-v-avtobusakh-v-podmoskove\">Правительство МО<\/a><\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>наличные<\/b><\/td>\n<td><b>Стрелка<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2018<\/td>\n<td>48 руб<\/td>\n<td>32,92 руб<\/td>\n<td><a href=\"https:\/\/zelenograd-news.ru\/news\/economics\/proezd_na_gorodskom_transporte_v_podmoskove_podorozhal_\">Зеленоград сегодня<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20220117170524\/https:\/\/mosreg.ru\/sobytiya\/novosti\/news-submoscow\/tarify-na-proezd-v-obschestvennom-transporte-podmoskovya-ne-prevysyat-4-v-2018-g-6198\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2017<\/td>\n<td>46 руб<\/td>\n<td>31,65 руб<\/td>\n<td><a href=\"https:\/\/rg.ru\/2017\/01\/01\/reg-cfo\/s-1-ianvaria-podorozhal-proezd-po-moskve-i-moskovskoj-oblasti.html\">Российская газета<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20221102032052\/https:\/\/rg.ru\/2017\/01\/01\/reg-cfo\/s-1-ianvaria-podorozhal-proezd-po-moskve-i-moskovskoj-oblasti.html\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2016<\/td>\n<td>43 руб<\/td>\n<td>30 руб<\/td>\n<td><a href=\"https:\/\/www.interfax-russia.ru\/center\/novosti-podmoskovya\/stoimost-proezda-v-avtobusah-podmoskovya-s-1-yanvarya-2016-goda-sostavit-43-rub-po-transportnoy-karte-30-rub\">Интерфакс<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20210617015900\/https:\/\/www.interfax-russia.ru\/center\/novosti-podmoskovya\/stoimost-proezda-v-avtobusah-podmoskovya-s-1-yanvarya-2016-goda-sostavit-43-rub-po-transportnoy-karte-30-rub\">архив<\/a><\/td>\n<\/tr>\n<\/table>\n<p>В 2015-2016 году появилась карта «Стрелка». За это время случилось много событий, смотрите сами:<\/p>\n<ul>\n<li>1 янв 2015. Очередное повышение тарифов до 28 рублей<\/li>\n<li>1 фев 2015. Появилась карта «Стрелка». Проезд по ней стоит те же 28 рублей, но с каждой 10-й поездкой стоимость снижается. 51-я поездка и далее стоят всего 18 рублей<\/li>\n<li>1 мая 2015. Появились ученическая и льготная «Стрелки». Проезд по ним стоит половину стандартного тарифа — 14 рублей<\/li>\n<li>30 мая 2015. Резко выросла цена на оплату наличными — 40 рублей. Проезд по «Стрелке» остался стоить столько же — 28 рублей. Видимо, нужно было стимулировать пассажиров, привыкших к наличным, использовать карты.<\/li>\n<li>1 янв 2016. Очередное повышение тарифов<\/li>\n<li>1 фев 2016. Появился супер-тариф для студентов со скидкой 99% начиная с 36-й поездки. До этого студенты платили фиксировано половину цены обычной «Стрелки» (к примеру, в 2016 году 50% от 30 рублей, то есть 15 рублей), а с 1 февраля — 15 рублей за первые 35 поездок и 1% от стандартной цены (1% от 30 рублей это 30 копеек) за все последующие поездки.<\/li>\n<\/ul>\n<p>Всё то же самое, но в таблице:<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>наличные<\/b><\/td>\n<td><b>Стрелка<\/b><\/td>\n<td><b>Уч. стрелка<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>1 фев 2016<\/td>\n<td>43 руб<\/td>\n<td>30 руб<\/td>\n<td>15 руб\/30 коп<\/td>\n<td><a href=\"https:\/\/mtdi.mosreg.ru\/sobytiya\/novosti-ministerstva\/09-02-2016-11-20-44-v-podmoskove-vvedena-99-protsentnaya-skidka-dlya-u\">Минтранс<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20160419095023\/http:\/\/odin.ru\/news\/?id=41264\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2016<\/td>\n<td>43 руб<\/td>\n<td>30 руб<\/td>\n<td>15 руб<\/td>\n<td><a href=\"https:\/\/www.interfax-russia.ru\/center\/novosti-podmoskovya\/stoimost-proezda-v-avtobusah-podmoskovya-s-1-yanvarya-2016-goda-sostavit-43-rub-po-transportnoy-karte-30-rub\">Интерфакс<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20210617015900\/https:\/\/www.interfax-russia.ru\/center\/novosti-podmoskovya\/stoimost-proezda-v-avtobusah-podmoskovya-s-1-yanvarya-2016-goda-sostavit-43-rub-po-transportnoy-karte-30-rub\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>30 мая 2015<\/td>\n<td>40 руб<\/td>\n<td>28 руб<\/td>\n<td>14 руб<\/td>\n<td><a href=\"https:\/\/www.m24.ru\/articles\/Podmoskove\/01062015\/75062\">Москва 24<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20160828221204\/https:\/\/strelkacard.ru\/project\/news\/137\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 мая 2015<\/td>\n<td>28 руб<\/td>\n<td>28 руб<\/td>\n<td>14 руб<\/td>\n<td><a href=\"https:\/\/strelkacard.ru\/project\/news\/216\">Стрелка<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20211128204948\/https:\/\/strelkacard.ru\/project\/news\/216\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 фев 2015<\/td>\n<td>28 руб<\/td>\n<td>28 руб<\/td>\n<td>—<\/td>\n<td><a href=\"https:\/\/strelkacard.ru\/project\/news\/193\">Стрелка<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20160908173909\/http:\/\/strelkacard.ru\/project\/news\/193\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2015<\/td>\n<td>28 руб<\/td>\n<td>—<\/td>\n<td>—<\/td>\n<td><a href=\"https:\/\/www.mskagency.ru\/materials\/1488077\">МСК-Агентство<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20250321012811\/https:\/\/www.gazeta.ru\/social\/2014\/11\/18\/6305677.shtml\">архив<\/a><\/td>\n<\/tr>\n<\/table>\n<p>Мы остановились на том, что в января 2015 проезд за наличные стоил 28 рублей. В 2014 году он стоил 26 рублей (<a href=\"https:\/\/www.mskagency.ru\/materials\/297031\">МСК-Агентство<\/a>). При этом, также можно было купить абонемент. Всего было доступно три типа абонементов — на 60 поездок, 100 поездок и студенческий безлимитный проездной на месяц.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>наличные<\/b><\/td>\n<td><b>60 п<\/b><\/td>\n<td><b>100 п<\/b><\/td>\n<td><b>студ<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2014<\/td>\n<td>26 руб<\/td>\n<td>940<\/td>\n<td>1490<\/td>\n<td>470<\/td>\n<td><a href=\"https:\/\/ria.ru\/20131126\/979706046.html?ysclid=mnlebqokd4373357123\">Риа<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2013<\/td>\n<td>25 руб<\/td>\n<td>870<\/td>\n<td>1380<\/td>\n<td>435<\/td>\n<td><a href=\"https:\/\/www.mk.ru\/moscow\/2012\/10\/23\/764973-poezdka-v-podmoskovnyih-avtobusah-podorozhaet.html?ysclid=mnlea2sfpq49599722\">Московский Комсомолец<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 фев 2011<\/td>\n<td>23 руб<\/td>\n<td>800<\/td>\n<td>1270<\/td>\n<td>400<\/td>\n<td><a href=\"https:\/\/kolomna-spravka.ru\/news\/2834?ysclid=m318hsi9dc630734010?utm_source=clipboard\">Коломна-Справка<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2010<\/td>\n<td>22 руб<\/td>\n<td>800<\/td>\n<td>1270<\/td>\n<td>400<\/td>\n<td><a href=\"https:\/\/www.interfax-russia.ru\/center\/news\/stoimost-proezda-obshchestvennym-transportom-v-podmoskove-s-novogo-goda-podorozhaet-na-10\">Интерфакс<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2009<\/td>\n<td>20 руб<\/td>\n<td>730<\/td>\n<td>1150<\/td>\n<td>365<\/td>\n<td><a href=\"https:\/\/kolomnatram.ruz.net\/news.php?year=2008\">КТ-Рузайн<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20160914163709\/https:\/\/kolomnatram.ruz.net\/news.php?year=2008\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 янв 2008<\/td>\n<td>17 руб<\/td>\n<td>600<\/td>\n<td>950<\/td>\n<td>300<\/td>\n<td><a href=\"https:\/\/kolomnatram.ruz.net\/news.php?year=2007\">КТ-Рузайн<\/a> · <a href=\"https:\/\/web.archive.org\/web\/20231210001625\/http:\/\/kolomnatram.ruz.net\/news.php?year=2007\">архив<\/a><\/td>\n<\/tr>\n<tr>\n<td>1 апр 2007<\/td>\n<td>15 руб<\/td>\n<td>500<\/td>\n<td>750<\/td>\n<td>250<\/td>\n<td><a href=\"https:\/\/regnum.ru\/news\/805739?ysclid=mnlezncmu1737443897\">Регнум<\/a><\/td>\n<\/tr>\n<\/table>\n<p>Обращаясь к источникам за 2006 год мы увидели, что веер проездных билетов изменился. Теперь есть такие виды:<\/p>\n<ul>\n<li>обычный билет (одна поездка)<\/li>\n<li>проездной на месяц<\/li>\n<li>проездной на квартал<\/li>\n<li>проездной на год<\/li>\n<li>проездной на месяц на два транспорта (например, автобус и трамвай)<\/li>\n<li>социальный проездной (для пенсионеров — да, раньше они катались за деньги)<\/li>\n<li>студентам доступны все проездные, кроме социального, за половину стоимости<\/li>\n<\/ul>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>1 поездка<\/b><\/td>\n<td><b>месяц<\/b><\/td>\n<td><b>квартал<\/b><\/td>\n<td><b>год<\/b><\/td>\n<td><b>А+Т<\/b><\/td>\n<td><b>соц<\/b><\/td>\n<td><b>студ<\/b><\/td>\n<td><b>источник<\/b><\/td>\n<\/tr>\n<tr>\n<td>1 мар 2006<\/td>\n<td>12 руб<\/td>\n<td>420 руб<\/td>\n<td>1110 руб<\/td>\n<td>4150 руб<\/td>\n<td>680 руб<\/td>\n<td>170 руб<\/td>\n<td>1\/2 стоимости<\/td>\n<td><a href=\"https:\/\/ria.ru\/20060301\/43838322.html?ysclid=mnyy31wpl0749932771\">Риа<\/a><\/td>\n<\/tr>\n<tr>\n<td>25 апр 2004<\/td>\n<td>10 руб<\/td>\n<td>400 руб<\/td>\n<td>1050 руб<\/td>\n<td>3950 руб<\/td>\n<td>650 руб<\/td>\n<td>150 руб<\/td>\n<td>175 руб<\/td>\n<td><a href=\"https:\/\/docs.cntd.ru\/document\/5810589?marker=6560IO\">Постановление<\/a><\/td>\n<\/tr>\n<\/table>\n<p>В 2002 году нас встречает лишь <a href=\"https:\/\/www.rbc.ru\/economics\/25\/11\/2002\/5703bfb19a7947afa08cdc0b?ysclid=mnyyd0t3vv963862525\">грустная статья от РБК<\/a>, где сообщается, что с 25 ноября разовый билет стоит 7 рублей, проездной на месяц — 310 рублей, проездной для студентов — 155 рублей.<\/p>\n<p>Для 2001 года даже распознать дату смены тарифов сложно. Мы предположили, что раз тарифы менялись в то время один раз в год, то изменение произошло 25 ноября 2001 года. <a href=\"https:\/\/www.oka.fm\/new\/read\/social\/Kak-menyalas-stoimost-proezda-v-podmoskovnyh-avtobusah\/?ysclid=mnyyi857k4180673766\">ОКА-ФМ сообщает<\/a>, что разовый билет тогда стоил 5 рублей, а до этого — 4 рубля.<\/p>\n<p>На этом интернет можно закрывать. Сколько бы мы ни пытались, но найти информацию о стоимости проезда в 20 веке в интернете не вышло — видимо, не был тогда он настолько сильно развит. На помощь приходит книга Романа Славацкого и Виктора Боченкова «Серебряное кольцо. Очерки истории коломенского трамвая». Вот что в ней пишется:<\/p>\n<blockquote>\n<p>В начале 90-х гг. инфляция приняла чудовищные размеры. Это можно проследить по ценам трамвайных талонов, которые в свое время продавались на остановках. Целыми десятилетиями мы платили за проездой раментальные три копейки. И эта сумма казалась незыблемой, как египетские пирамиды. Но в августе 1991 года цена подскочила в пять раз! Прошло полгода — и билет стоил уже 50 копеек. А в июле 1992 года за него просили рубль. М.М. Фарберов, как мог, убеждал областное правительство не повышать стоимость проезда. Ведь чем выше цена, тем меньше возможности приобрести билет. Но все доводы остались без внимания.<\/p>\n<\/blockquote>\n<blockquote>\n<p>И вот в августе 1993 года за билет пришлось отдавать 10 рублей, а с ноября — уже 20. В январе коломенцев ждал новогодний «подарок»: с 15 числа за проезд брали 40 рублей. С началом весны «расцвела» и цена; в ход пошла сотня.<\/p>\n<\/blockquote>\n<blockquote>\n<p>Проблема была в том, что билеты перестали приобретать многие коломенцы, и не потому, что у них вдруг резко испортился характер — просто у людей не хватало денег...<\/p>\n<\/blockquote>\n<blockquote>\n<p>В безумной инфляционной гонке, развязанной экономическими «экспериментаторами», превратились в ничто многолетние накопления людей, обрушилась промышленность, разваливалась инфраструктура...<\/p>\n<\/blockquote>\n<p>Что ж, спасибо авторам этой прекрасной книги! Заполняем пропуски в нашей истории цен.<\/p>\n<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" class=\"e2-text-table\">\n<tr>\n<td><b>с какой даты<\/b><\/td>\n<td><b>стоимость<\/b><\/td>\n<\/tr>\n<tr>\n<td>15 мар 1994<\/td>\n<td>100 руб<\/td>\n<\/tr>\n<tr>\n<td>15 янв 1994<\/td>\n<td>40 руб<\/td>\n<\/tr>\n<tr>\n<td>ноя 1993<\/td>\n<td>20 руб<\/td>\n<\/tr>\n<tr>\n<td>авг 1993<\/td>\n<td>10 руб<\/td>\n<\/tr>\n<tr>\n<td>июль 1992<\/td>\n<td>1 руб<\/td>\n<\/tr>\n<tr>\n<td>фев 1992<\/td>\n<td>50 коп<\/td>\n<\/tr>\n<tr>\n<td>авг 1991<\/td>\n<td>15 коп<\/td>\n<\/tr>\n<tr>\n<td>5 ноя 1948<\/td>\n<td>3 коп<\/td>\n<\/tr>\n<\/table>\n<p>Допустим, мы незадачливый путешественник во времени, который попал в каждую эпоху и решил совершить одну поездку на трамвае. Вот сколько стоит самый дешевый для него проезд в разные года.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tariffs-history-1.png\" width=\"2314\" height=\"936\" alt=\"\" \/>\n<\/div>\n",
            "summary": "Открытых данных по стоимости проезда в одном месте нигде не было, поэтому пришлось искать эту информацию в разных источниках. Мы собрали всю информацию в одном месте.",
            "date_published": "2026-04-14T21:56:57+03:00",
            "date_modified": "2026-04-16T13:06:48+03:00",
            "tags": [
                "аналитика данных",
                "красная таблетка",
                "машина времени"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tariffs-history.png",
            "_date_published_rfc2822": "Tue, 14 Apr 2026 21:56:57 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "4",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": true,
                "links_required": [],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tariffs-history.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tariffs-history-1.png"
                ]
            }
        },
        {
            "id": "19",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/preprint-crowd\/",
            "title": "Вышла статья «Прогнозирование загруженности трамваев методами машинного обучения»",
            "content_html": "<p>Вышла статья «Прогнозирование загруженности трамваев методами машинного обучения» в Институте прикладной математики им. М.В. Келдыша Российской академии наук.<\/p>\n<p>Написали статью разработчик и автор проекта Дмитрий Балабанов и его научный сотрудник Владимир Судаков.<\/p>\n<p>В статье рассказывается о том, как мы разработали модель машинного обучения для прогнозирования загруженности вагонов трамваев в Коломне. Мы собрали и обработали данные за период с сентября 2024 по июнь 2025 года: GPS-треки трамваев, погоду, расписание пригородных поездов, количество остановок и мест притяжения (ТЦ, школы, вокзалы). Особенность нашего подхода — адаптация моделей к условиям малого города с ограниченным объёмом данных и упор на интерпретируемость результатов для пассажиров.<\/p>\n<p>Мы сравнили три модели: линейную регрессию, случайный лес и градиентный бустинг. Лучший результат показал случайный лес (R² = 0,87, MAPE = 31%). Модель обучили без привязки к номеру маршрута, чтобы она могла работать с любыми маршрутами, ориентируясь на расстояния до остановок. Готовую модель внедрили в веб-сервис, где загруженность показывается не числом людей, а понятными значками.<\/p>\n<p>Подробнее о проекте можно узнать здесь в блоге по тегу <a href=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/tags\/crowd-predict\/\">«прогнозирование загруженности».<\/a><\/p>\n<p>Почитать о статье можно здесь.<br \/>\n<a href=\"https:\/\/library.keldysh.ru\/preprint.asp?id=2026-12\">https:\/\/library.keldysh.ru\/preprint.asp?id=2026-12<\/a><\/p>\n<p>А саму статью (бесплатно) — здесь.<br \/>\n<a href=\"https:\/\/keldysh.ru\/papers\/2026\/prep2026_12.pdf\">https:\/\/keldysh.ru\/papers\/2026\/prep2026_12.pdf<\/a><\/p>\n",
            "summary": "Вышла статья «Прогнозирование загруженности трамваев методами машинного обучения» в Институте прикладной математики им...",
            "date_published": "2026-04-09T15:00:00+03:00",
            "date_modified": "2026-04-28T17:28:01+03:00",
            "tags": [
                "аналитика данных",
                "ИМП им. Келдыша",
                "машинное обучение",
                "прогнозирование загруженности",
                "статья"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/crowd-predict.png",
            "_date_published_rfc2822": "Thu, 09 Apr 2026 15:00:00 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "19",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": false,
                "links_required": [],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/crowd-predict.png"
                ]
            }
        },
        {
            "id": "8",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/stops-search\/",
            "title": "Поиск остановок",
            "content_html": "<p>На не самой популярной странице <a href=\"https:\/\/kolomna-trams.ru\/route\/stops\/\" class=\"nu\">«<u>Остановки<\/u>»<\/a> есть функция поиска. Например:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stops-search.png\" width=\"2172\" height=\"1606\" alt=\"\" \/>\n<\/div>\n<p>Поиск умеет работать даже если допустить ошибку в слове. Можно даже не одну ошибку.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stops-search-1.png\" width=\"2172\" height=\"1606\" alt=\"\" \/>\n<\/div>\n<p>А ещё можно так:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stops-search-2.png\" width=\"2172\" height=\"1606\" alt=\"\" \/>\n<\/div>\n<p>Всё это работает в браузере без машинного обучения и искусственного интеллекта.<\/p>\n<p>Формально задача звучит так: есть функция get_search_results, которая получает текст запроса и возвращает список остановок, которые пользователь мог иметь в виду.<\/p>\n<pre class=\"e2-text-code\"><code class=\"js\">function get_search_results(prompt) {\n    ...\n}<\/code><\/pre><p>Самый простой способ — искать вхождение подстроки. Если пользователь ввёл «Калинина», найти все остановки, в названии которых есть «Калинина». Это работает, но только если пользователь не ошибся.<\/p>\n<p>А если ошибся? Например, написал «Калинино» или «Калининв»?<\/p>\n<p>Тогда нужен механизм, который умеет прощать ошибки.<\/p>\n<h2>Первый подход: перебор<\/h2>\n<p>Мы решили, что будем перебирать все возможные подстроки запроса и смотреть, сколько из них встречается в названии остановки. Чем больше совпадений — тем вероятнее, что пользователь имел в виду именно эту остановку.<\/p>\n<p>Например, пользователь ввёл «Калининва». Разбиваем на подстроки разной длины:<br \/>\n— Длина 1: «К», «а», «л», «и», «н», «и», «н», «в», «а»<br \/>\n— Длина 2: «Ка», «ал», «ли», «ин», «ни», «ин», «нв», «ва»<br \/>\n— Длина 3: «Кал», «али», «лин», «ини», «нин», «инв», «нва»<br \/>\n— И так далее.<\/p>\n<p>Потом смотрим, сколько из этих подстрок встречается в названии «Улица Калинина». Чем больше — тем выше точность.<\/p>\n<p>Для коротких запросов, например «Кали», этот метод тоже работает: подстроки «К», «а», «л», «и», «Ка», «ал», «ли», «Кал», «али» — почти все найдутся в названии.<\/p>\n<p>Но тут есть нюанс<\/p>\n<p>Если запрос длинный, количество подстрок растёт квадратично. Для слова из 10 букв это 55 подстрок. Для 15 — уже 120. Перебирать 120 подстрок для каждой из сотни остановок — на клиенте это всё равно быстро, но мы решили ограничить максимальную длину запроса семью символами. Если пользователь ввёл длинное слово, дальше семи букв мы подстроки не режем.<\/p>\n<p>Вот как выглядит основная логика:<\/p>\n<pre class=\"e2-text-code\"><code class=\"js\">for (let i = 1; i &lt;= prompt.length; i++) {\n    if (i &gt;= 7) break;\n    for (let j = 0; j &lt; prompt.length - i + 1; j++) {\n        const sub = prompt.substring(j, j + i);\n        if (stp.Name.toLowerCase().includes(sub)) {\n            acc_count += 1;\n        }\n    }\n}<\/code><\/pre><p>Счётчик acc_count накапливает количество совпадений. Потом мы делим его на максимально возможное количество совпадений для запроса этой длины. Получается число от 0 до 1 — степень уверенности, что остановка подходит.<\/p>\n<h2>Альтернативные названия<\/h2>\n<p>В Коломне у некоторых остановок есть народные названия. Например, «Трамвайное управление» в народе — просто «Депо». А остановка «Детская художественная школа» иногда называется «Путепровод» или «Холодильник» (что?).<\/p>\n<p>Мы добавили массив Alternatives для каждой остановки. Если подстрока не нашлась в официальном названии, но нашлась в одном из альтернативных, мы тоже добавляем очко, но с понижающим коэффициентом. Потому что альтернативное название — это всё-таки не основное.<\/p>\n<pre class=\"e2-text-code\"><code class=\"js\">for (const alt of stp.Alternatives) {\n    if (alt.includes(sub)) {\n        acc_count += 1 \/ stp.Alternatives.length;\n    }\n}<\/code><\/pre><p>Нашлось ещё одно применение Alternatives — разные написания названий. К примеру, для «Площади двух революций» добавили «Площадь 2 революций» — потому что люди часто заменяют слово «двух» на цифру. А для «Бульвара 800-летия Коломны» добавили «Бульвар восьмисотлетия Коломны» — кто-то вводит и так.<\/p>\n<h2>Порог срабатывания<\/h2>\n<p>На основе этого механизма мы написали отдельную функцию get_search_results_improved, которая возвращает все остановки, у которых степень уверенности превысила порог accuracy.<\/p>\n<p>А порог accuracy вычисляем эмпирически:<\/p>\n<pre class=\"e2-text-code\"><code class=\"js\">let accuracy = search_results.length * 0.02 + prompt.length * 0.01 + 0.25;<\/code><\/pre><p>Если обычный поиск (простое вхождение) нашёл много результатов — порог повышаем, чтобы не выдавать мусор. Если запрос длинный — тоже повышаем, потому что длинный запрос точнее.<\/p>\n<h2>А что, если пользователь ввёл всё правильно<\/h2>\n<p>Если пользователь не ошибся, зачем запускать тяжёлый алгоритм с подстроками? Поэтому в get_search_results сначала идут простые проверки:<\/p>\n<ol start=\"1\">\n<li>Точное совпадение с учётом заглавной буквы<\/li>\n<li>Совпадение с пробелом перед запросом (чтобы найти слово в середине названия)<\/li>\n<li>Простое вхождение в нижнем регистре<\/li>\n<li>Поиск по альтернативным названиям<\/li>\n<\/ol>\n<p>Только после этого, если простые методы сработали, запускаем улучшенный поиск и докладываем его результаты сверху.<\/p>\n<pre class=\"e2-text-code\"><code class=\"js\">search_results.push(...get_search_results_improved(prompt, accuracy));<\/code><\/pre><h2>Дубликаты и ограничения<\/h2>\n<p>Одна и та же остановка может попасть в результаты несколько раз — например, нашлась и по точному совпадению, и через альтернативное название. Поэтому после всех операций мы прогоняем список через removeDuplicates.<\/p>\n<p>И в конце оставляем не больше семи результатов. Семь — хорошее число. Не перегружает интерфейс, но даёт достаточно выбора.<\/p>\n<pre class=\"e2-text-code\"><code class=\"js\">search_results = search_results.slice(0, 7);<\/code><\/pre><h2>Почему не Левенштейн<\/h2>\n<p>Знающие люди спросят: а почему вы не использовали расстояние Левенштейна? Оно же специально придумано для поиска с ошибками.<\/p>\n<p>Расстояние Левенштейна считает, сколько букв нужно заменить, удалить или добавить, чтобы одно слово превратилось в другое. Казалось бы, идеально.<\/p>\n<p>Но есть проблема. Остановка может называться «Улица Калинина», а пользователь вводит «Калинина». Расстояние Левенштейна будет большим, потому что в начале названия не хватает «Улица ». А наш алгоритм разбивает на подстроки и находит «Калинина» внутри, потому что «Калинин» и «Калинина» — это общие куски.<\/p>\n<p>К тому же, Левенштейн не умеет работать с альтернативными названиями. А наш умеет.<\/p>\n",
            "summary": "На не самой популярной странице \"Остановки\" есть функция поиска. Поиск умеет работать даже если допустить ошибку в слове. Всё это работает в браузере без машинного обучения и искусственного интеллекта.",
            "date_published": "2026-03-22T20:44:16+03:00",
            "date_modified": "2026-03-22T20:47:09+03:00",
            "tags": [
                "алгоритмы",
                "код",
                "фронтенд"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stops-search.png",
            "_date_published_rfc2822": "Sun, 22 Mar 2026 20:44:16 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "8",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": true,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stops-search.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stops-search-1.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stops-search-2.png"
                ]
            }
        },
        {
            "id": "6",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/page-404\/",
            "title": "Страница 404",
            "content_html": "<p>Когда человек заходит на несуществующую страницу, обычно ему показывают какую-то скучную надпись вроде «Страница не найдена». Нам это всегда казалось невежливым. Человек уже потерялся, а его ещё и казённым языком встречают.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stranica-404.png\" width=\"2332\" height=\"1632\" alt=\"\" \/>\n<\/div>\n<p>Потом мы заметили, что на многих хороших сайтах к 404 подходят не как к ошибке, а как к возможности. Причём самые удачные варианты — те, где страница ошибки продолжает тему сайта.<\/p>\n<div class=\"e2-text-picture\">\n<div class=\"fotorama\" data-width=\"2332\" data-ratio=\"1.4289215686275\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-4.png\" width=\"2332\" height=\"1632\" alt=\"\" \/>\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-5.png\" width=\"2332\" height=\"1632\" alt=\"\" \/>\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404.png\" width=\"2332\" height=\"1632\" alt=\"\" \/>\n<\/div>\n<div class=\"e2-text-caption\">Самые крутые примеры:<br \/>\n<a href=\"https:\/\/www.fdoctor.ru\/page404\/\">https:\/\/www.fdoctor.ru\/page404\/<\/a><br \/>\n<a href=\"https:\/\/arzamas.academy\/page404\">https:\/\/arzamas.academy\/page404<\/a><br \/>\n<a href=\"https:\/\/www.hse.ru\/page404\">https:\/\/www.hse.ru\/page404<\/a> (каждый раз разная)<\/div>\n<\/div>\n<p>Нам всегда нравился такой подход. Страница ошибки перестаёт быть просто ошибкой. Она становится частью бренда, маленькой шуткой, которую поймёт свой.<\/p>\n<p>И вот в какой-то момент мы сидели и думали: а что связано с Коломной, с трамваями, с темой сайта, что может быть одновременно и ошибкой, и нормальным предметом?<\/p>\n<p>Билет.<\/p>\n<p>Трамвайный билет. На нём есть номер. А 404 — это же просто номер. Не «ошибка 404», а просто билет номер 000404. Никто даже не поймёт, что это техническая деталь, пока не присмотрится.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/C47917E3-D737-4D39-BE2B-3F2AB5E523A8_1_102_o.jpeg\" width=\"2048\" height=\"1536\" alt=\"\" \/>\n<\/div>\n<p>Тот самый случай, когда техническая деталь становится частью дизайна, а не торчит наружу.<\/p>\n<p>Конечно, сейчас таких билетов уже не найти. Не получится просто покататься на трамвае и ждать, пока кондуктор выдаст тебе билет с нужным номером. Но нам повезло: мы нашли образец билета в интернете.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-2.png\" width=\"1143\" height=\"834\" alt=\"\" \/>\n<div class=\"e2-text-caption\"><a href=\"https:\/\/shablon.klev.club\/uploads\/posts\/2024-09\/shablon-klev-club-uaec-p-shabloni-bileti-na-tramvai-9.jpg\">https:\/\/shablon.klev.club\/uploads\/posts\/2024-09\/shablon-klev-club-uaec-p-shabloni-bileti-na-tramvai-9.jpg<\/a><\/div>\n<\/div>\n<p>Как раз и нужные цифры (0 и 4) здесь есть, не придётся ничего изобретать. Осталось только нафотошопить нужный билет.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/404.jpg\" width=\"572\" height=\"834\" alt=\"\" \/>\n<\/div>\n<p>И затем распечатать. Можно даже немного побольше по размеру, чем настоящий билет — всё равно ведь никто не проверит, а качество фото будет лучше. Чтобы создать впечатление настоящего билета, мы его немного порвали с краев и помяли. Без этого выглядит слишком чисто, сразу видно подделку.<\/p>\n<p>Осталось сфотографировать. На странице билет будет на белом фоне, поэтому под билет надо подложить белый лист бумаги. Основная проблема здесь — правильно выставить свет. Например, поначалу у нас была такая картинка с довольно жёсткой тенью.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-1.png\" width=\"2332\" height=\"1632\" alt=\"\" \/>\n<\/div>\n<p>Потом переставили лампу, чтобы тень была мягкой<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/IMG_5993.jpeg.jpg\" width=\"2560\" height=\"1999\" alt=\"\" \/>\n<\/div>\n<p>Но тут вылезла другая проблема. Лист бумаги белый, но камера его не может снять таким же белым, как чисто-белый фон сайта. На сайте фон #FFFFFF, а на фотографии — сероватый.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-6.png\" width=\"2154\" height=\"1402\" alt=\"\" \/>\n<\/div>\n<p>Пришлось выбеливать фотографию в редакторе, чтобы фон стал идеально белым и слился с фоном страницы.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404.png.jpg\" width=\"2560\" height=\"1311\" alt=\"\" \/>\n<\/div>\n<p>Вот что получилось в итоге.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-3.png\" width=\"2318\" height=\"1632\" alt=\"\" \/>\n<\/div>\n<p>Под билетом — надпись «Потерялись?». А ещё ниже — подпись. Она меняется каждый раз при обновлении страницы. Это просто маленькая игра. Кто-то обновит страницу пару раз и найдёт для себя подходящую.<\/p>\n<p>Кстати, технически здесь нет никакой магии. Обычный .htaccess направляет все 404-е ошибки на специальный php-файл. Внутри — массив с фразами и функция shuffle().<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-4.png\" width=\"1906\" height=\"1312\" alt=\"\" \/>\n<\/div>\n<p>Ну и если вы вдруг забредёте на несуществующую страницу — теперь знаете, какой билет вам выдадут.<\/p>\n<p><a href=\"https:\/\/kolomna-trams.ru\/page404\/\">https:\/\/kolomna-trams.ru\/page404\/<\/a><\/p>\n",
            "summary": "Когда человек заходит на несуществующую страницу, обычно ему показывают какую-то скучную надпись вроде «Страница не найдена»",
            "date_published": "2026-03-22T15:08:16+03:00",
            "date_modified": "2026-04-16T11:49:03+03:00",
            "tags": [
                "дизайн",
                "пасхалки",
                "фронтенд"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stranica-404.png",
            "_date_published_rfc2822": "Sun, 22 Mar 2026 15:08:16 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "6",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": true,
                "links_required": [
                    "jquery\/jquery.js",
                    "fotorama\/fotorama.css",
                    "fotorama\/fotorama.js"
                ],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/stranica-404.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-4.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-5.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/C47917E3-D737-4D39-BE2B-3F2AB5E523A8_1_102_o.jpeg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-2.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/404.jpg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-1.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/IMG_5993.jpeg.jpg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-6.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404.png.jpg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-3.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/page-404-4.png"
                ]
            }
        },
        {
            "id": "3",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/tram-arrives-in-5-minutes\/",
            "title": "Трамвай будет через 5 минут",
            "content_html": "<p>Посмотрите на скриншот.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tram-arrives-in-5-mins-1.png\" width=\"2430\" height=\"1712\" alt=\"\" \/>\n<\/div>\n<p>Казалось бы, ничего необычного, да? Ближайший трамвай — через 5 минут.<\/p>\n<p>А теперь вопрос со звёздочкой. Если мы сейчас находимся в другом часовом поясе, что это значит? Трамвай будет <i>по-настоящему<\/i> через 5 минут? Или это значит, что он должен был бы быть через 5 минут, если бы в Коломне было столько же времени, сколько в нашем часовом поясе?<\/p>\n<p>Чтобы убрать все возможные недоразумения на этот счёт, в другом часовом поясе интерфейс отображает крупно время прибытия трамвая, а также текущее время в Коломне. Теперь всем понятно: сейчас в Коломне 09:26, трамвай будет в 09:31 по коломенскому времени, то есть через 5 минут. Никакой магии относительности.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tram-arrives-in-5-mins.png\" width=\"2430\" height=\"1712\" alt=\"\" \/>\n<\/div>\n<p>Теперь о том, как это работает под капотом. Когда сервер собирает страницу, он встраивает в HTML своё текущее время. Браузер это время считывает и вычисляет разницу со своим. Если разница нулевая — значит, пользователь сидит в том же часовом поясе, и интерфейс просто показывает «через 5 минут».<\/p>\n<p>Если разница не равна нулю, то браузер вычисляет разницу и отображает время с её учётом (то есть любой вызов функции Date.now() прибавляет ко времени эту разницу).<\/p>\n<p>Дело закрыто.<\/p>\n",
            "summary": "Посмотрите на скриншот",
            "date_published": "2026-03-19T12:34:00+03:00",
            "date_modified": "2026-03-22T10:01:06+03:00",
            "tags": [
                "архитектура",
                "бэкенд",
                "время",
                "расписание",
                "фронтенд"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tramvay-budet-cherez-5-minut.png",
            "_date_published_rfc2822": "Thu, 19 Mar 2026 12:34:00 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "3",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": true,
                "links_required": [],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tramvay-budet-cherez-5-minut.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tramvay-budet-cherez-5-minut-1.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tram-arrives-in-5-mins-1.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/tram-arrives-in-5-mins.png"
                ]
            }
        },
        {
            "id": "1",
            "url": "https:\/\/kolomna-trams.ru\/workshop\/articles\/all\/route-building\/",
            "title": "Как работает построение маршрута",
            "content_html": "<p>Есть на сайте одна простая фича — построить маршрут между двумя остановками.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building.png\" width=\"2440\" height=\"1586\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Маршрут на схеме от «Площади двух революций» до «Весенней улицы». Попробуйте сами: <a href=\"https:\/\/kolomna-trams.ru\/route\/map\/#from=0101&to=1202\">https:\/\/kolomna-trams.ru\/route\/map\/#from=0101&to=1202<\/a><\/div>\n<\/div>\n<p>Выбираешь остановку А, выбираешь остановку Б — получаешь список, где сесть и где пересесть.<\/p>\n<p>На первый взгляд кажется: ну что там сложного? Взял граф, нашел кратчайший путь, вывел на экран. Но всё сложнее. Как должен выглядеть граф? Что считать вершинами? Какие веса дать рёбрам? И главное — в какой момент человеку нужно пересесть на другой трамвай?<\/p>\n<p>Первое, что приходит в голову — сделать граф, где вершины — это остановки, а рёбра — перегоны между ними. Сеть в Коломне маленькая, поэтому для поиска пути мы можем использовать алгоритм Дейкстры.<\/p>\n<p>Дейкстре нужен взвешенный граф. Логичнее всего в качестве веса взять реальное время в пути. Поэтому мы собрали данные по всем соседним остановкам: посмотрели расписание, сверились с онлайн-картами, посчитали время и сложили всё в базу.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-2.png\" width=\"1740\" height=\"1210\" alt=\"\" \/>\n<\/div>\n<p>Кстати, эта функция доступна и по API. Вот, например, сколько ехать от «Студенческой» до «Улицы Калинина» в секундах:<\/p>\n<blockquote>\n<p><a href=\"https:\/\/kolomna-trams.ru\/api\/shuttletime?from=0501aF&to=0502aF\">https:\/\/kolomna-trams.ru\/api\/shuttletime?from=0501aF&to=0502aF<\/a><\/p>\n<\/blockquote>\n<pre class=\"e2-text-code\"><code class=\"\">{\n    &quot;ok&quot;: &quot;true&quot;,\n    &quot;result&quot;: {\n        &quot;time&quot;: 120\n    }\n}<\/code><\/pre><p>Как работает алгоритм Дейкстры. Присваиваем начальной точке графа (точке отправления) число 0, остальным — бесконечность.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-4.png\" width=\"1958\" height=\"1346\" alt=\"\" \/>\n<\/div>\n<p>Затем выбираем вершину с минимальным значением (на первом шаге — начальная точка, поскольку 0 < ∞) и смотрим, с какими вершинами она связана. Новое значение для каждой из вершин находится как значение текущей вершины + вес связи.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-5.png\" width=\"1976\" height=\"1360\" alt=\"\" \/>\n<\/div>\n<p>При этом, если случится такое, что старое значение вершины меньше, чем рассчитанное, то мы его не трогаем (это означает, что на одном из прошлых шагов был найден маршрут оптимальнее).<\/p>\n<p>Как только все связи обработаны, вершина помечается как «рассмотренная» и далее не учитывается. Весь алгоритм повторяется, пока все вершины не станут «рассмотренными». На втором этапе изучается одна из вершин, значение для которой пересчитано на первом шаге.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-8.png\" width=\"1962\" height=\"1340\" alt=\"\" \/>\n<div class=\"e2-text-caption\">Здесь как раз видно, что 4 не заменяет 0: до «Площади двух революций» можно добраться быстрее, чем за 4 минуты<\/div>\n<\/div>\n<p>На третьем шаге опять выбираем нерассмотренную вершину с наименьшим значением («Конькобежный центр»), на четвёртом шаге — «Пионерская улица».<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-7.png\" width=\"1866\" height=\"1276\" alt=\"\" \/>\n<\/div>\n<p>Когда все вершины рассмотрены, для каждой указано минимальное время. Остается только взять остановку назначения — и вот он готовый маршрут.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-9.png\" width=\"1892\" height=\"470\" alt=\"\" \/>\n<\/div>\n<p>Но пользователю не нужен просто список остановок. Ему нужны номера трамваев и места пересадок. В построенном маршруте, например, нет прямого рейса трамвая.<\/p>\n<p>Сначала мы делаем просто: берем первое ребро нашего маршрута и смотрим, какие трамваи по нему едут. В нашем примере это 1, 3, 7 и 9.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-1.png\" width=\"2388\" height=\"608\" alt=\"\" \/>\n<\/div>\n<p>Для второго ребра — снова смотрим. Пока наборы маршрутов совпадают — всё хорошо.<\/p>\n<p>Но в какой-то момент наборы расходятся.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-2.png\" width=\"2212\" height=\"616\" alt=\"\" \/>\n<\/div>\n<p>Если в новом наборе есть хоть один маршрут из старого, значит, мы можем продолжать ехать без пересадки.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-10.png\" width=\"2292\" height=\"598\" alt=\"\" \/>\n<\/div>\n<p>В нашем примере рано или поздно наборы становятся пустыми. Это значит, что без пересадки не обойтись. Тогда мы отрезаем кусок от начала до последней остановки, где набор ещё не был пуст, и начинаем строить заново с того места, где маршруты разошлись.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-11.png\" width=\"2392\" height=\"302\" alt=\"\" \/>\n<\/div>\n<p>Шаг 4. Алгоритм повторяется, пока мы не достигнем точки назначения.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image.png-1.jpg\" width=\"2560\" height=\"328\" alt=\"\" \/>\n<\/div>\n<p>В итоге получается маршрут из нескольких частей. Для каждой части есть список подходящих трамваев. Осталось только красиво их показать на карточке.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-3.png\" width=\"1180\" height=\"750\" alt=\"\" \/>\n<\/div>\n<p>Но если вы откроете <a href=\"https:\/\/kolomna-trams.ru\/route\/map\/#from=0100&to=1202\">сайт и построите тот же маршрут,<\/a> он будет немного отличаться от нашего примера.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-14.png\" width=\"1178\" height=\"750\" alt=\"\" \/>\n<\/div>\n<p>Отчего так? Дело в том, что в Коломне есть редкие маршруты, например № 7, который ходит раз в 40 минут. Алгоритм предлагает ехать на нём, но это неудобно. В то же время можно без ущерба смыслу маршрута выйти на несколько остановок раньше, зато иметь возможность ехать на трамвае № 3, который ходит каждые 10-12 минут (а вкупе с тем, что № 7 нам тоже всё ещё подходит, время ожидания на остановке ещё снижается).<\/p>\n<p>Можно было бы, конечно, вычислять на каждом шаге ещё и среднее время ожидания трамвая и как-то его сравнивать с каким-то пороговым значением, однако здесь был использован более простой метод. Всего в Коломне таких «редких» маршрутов пять: № 6, 7, 8, 9 и 10. Мы просто сказали алгоритму: считай, что наборы, состоящие только из редких маршрутов, — это пустые наборы. Так алгоритм начинает искать альтернативы с более частыми трамваями.<\/p>\n<p>Но не всё так просто. Вот такой маршрут будет построен неверно:<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image.png\" width=\"2028\" height=\"1466\" alt=\"\" \/>\n<\/div>\n<p>Алгоритм подумает, что можно без пересадок добраться на трамвае № 4, проехав четыре остановки. На самом деле нужно проехать две, выйти и сесть на тот же четвертый, но в обратную сторону.<\/p>\n<p>Чтобы это починить, мы усложнили граф. Теперь вершина — это не просто остановка, а конкретная платформа (в одну или другую сторону). Между платформами одного остановочного пункта мы добавили ребро с временем в полминуты.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-12.png\" width=\"1662\" height=\"1034\" alt=\"\" \/>\n<\/div>\n<blockquote>\n<p><a href=\"https:\/\/kolomna-trams.ru\/api\/shuttletime?from=0501aF&to=0501aB\">https:\/\/kolomna-trams.ru\/api\/shuttletime?from=0501aF&to=0501aB<\/a><\/p>\n<\/blockquote>\n<pre class=\"e2-text-code\"><code class=\"\">{\n    &quot;ok&quot;: &quot;true&quot;,\n    &quot;result&quot;: {\n        &quot;time&quot;: 30\n    }\n}<\/code><\/pre><p>Разбиение маршрута на части проходит по той же схеме с одним лишь отличием: переходы между остановками автоматически «сбрасывают» набор рассматриваемых маршрутов.<\/p>\n<p>Но и это ещё не всё. Мы научили алгоритм строить сложные маршруты, но теперь он ломается на простых.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image.png.jpg\" width=\"2560\" height=\"1529\" alt=\"\" \/>\n<\/div>\n<p>Вместо того чтобы просто ехать на одной «семёрке», он выдавал маршрут с четырьмя пересадками, хотя на последнем участке всё равно был только седьмой маршрут, а значит, нет никакого смысла садиться на трамваи других маршрутов, нужно с самого начала ждать «семёрку», как бы редко она ни ходила.<\/p>\n<p>Мы добавили правило: если набор маршрутов одной из частей полностью входит в набор маршрутов другой части и для пересадки не нужно переходить на другую сторону, мы склеиваем их в одну. Маршруты склеиваются до тех пор, пока это возможно.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-13.png\" width=\"1384\" height=\"608\" alt=\"\" \/>\n<\/div>\n<p>Так все части по очереди склеятся друг с другом (начиная с конца), и в итоге останется один беспересадочный маршрут с одним возможным трамваем.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-3.png\" width=\"2028\" height=\"1466\" alt=\"\" \/>\n<\/div>\n<p>Поскольку все эти вычисления занимают мало времени, мы сделали так, чтобы скрипт работал прямо в браузере. Бэкенд тут вообще не участвует.<\/p>\n<p>Отдельно мы сделали подсветку на схеме. Когда вы строите маршрут, схема «гаснет», и только нужные линии остаются яркими. Это оказалось несложно: мы разобрали векторную схему на части, записали их в память, а потом просто проходим по маршруту и показываем нужные куски.<\/p>\n<p>И ещё одна мелочь. Какой-нибудь невнимательный человек может решить построить маршрут от одной остановки до неё же самой. Это не ошибка, но надо как-то намекнуть, что он делает что-то не так. Лепить модальное окно — это перебор. Поэтому мы просто сделали так, что название остановки слегка дёргается. Типа: «ты уже здесь, выбери другую».<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-03-18-at-15.58.16.gif\" width=\"1452\" height=\"1096\" alt=\"\" \/>\n<\/div>\n<p>Бонусом — кнопка «Обратный маршрут». В большинстве случаев обратный путь — это просто поехать тем же трамваем, но в другую сторону. Чтобы это было наглядно, мы придумали такую анимацию.<\/p>\n<div class=\"e2-text-picture\">\n<img src=\"https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-03-18-at-16.01.47.gif\" width=\"1984\" height=\"1378\" alt=\"\" \/>\n<\/div>\n<p>На этом всё. Получилось, что за простой с виду функцией стоит довольно много возни.<\/p>\n",
            "summary": "Есть на сайте одна простая фича — построить маршрут между двумя остановками",
            "date_published": "2026-03-18T16:03:00+03:00",
            "date_modified": "2026-04-15T14:27:14+03:00",
            "tags": [
                "алгоритмы",
                "маршруты",
                "фронтенд"
            ],
            "image": "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-1.png",
            "_date_published_rfc2822": "Wed, 18 Mar 2026 16:03:00 +0300",
            "_rss_guid_is_permalink": "false",
            "_rss_guid": "1",
            "_rss_enclosures": [],
            "_e2_data": {
                "is_favourite": true,
                "links_required": [
                    "highlight\/highlight.js",
                    "highlight\/highlight.css"
                ],
                "og_images": [
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-1.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building.png.jpg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-03-17-at-22.30.50-2.gif",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-03-17-at-22.38.15.gif",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-6.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-2.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-4.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-5.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-8.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-7.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-9.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-1.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-2.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-10.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-11.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image.png-1.jpg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image-3.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-14.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-12.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/image.png.jpg",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-13.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/route-building-3.png",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-03-18-at-15.58.16.gif",
                    "https:\/\/kolomna-trams.ru\/workshop\/articles\/pictures\/Adobe-Express---Screen-Recording-2026-03-18-at-16.01.47.gif"
                ]
            }
        }
    ],
    "_e2_version": 4199,
    "_e2_ua_string": "Aegea 11.5 (v4199e)"
}