Как мы расписание общественного транспорта в 2ГИС добавляли

Как мы расписание общественного транспорта в 2ГИС добавляли

2ГИС помогает ориентироваться в городе. Открываешь приложение, вводишь в поиск название улицы или организации, находишь, радуешься. После того, как нужная организация найдена, возникает резонный вопрос: как же туда добраться? И если автомобильным сценариям мы в последнее время уделяли значительное внимание, то поиск проезда на общественном транспорте оказался немного подзабыт. Я расскажу про то, как создавался поиск проезда, поделюсь тонкостями сбора и обработки информации.

Откуда взялась задача

Мы любим общаться с пользователями. В конце 2016 года мы провели опрос, дабы выяснить, как пользуются общественным транспортом наши пользователи. Результат получился любопытным — делимся.

«Как часто вы пользуетесь общественным транспортом?»

В целом, во всех городах присутствия 2ГИС более половины респондентов пользуются общественным транспортом каждый день. Чем крупнее город, тем больше людей использует общественный транспорт ежедневно. В будние дни он максимально популярен у жителей Москвы и Санкт-Петербурга, а в остальных городах люди активно пользуются общественным транспортом и в выходные.

С частотой использования разобрались, время посмотреть, какие виды общественного транспорта — фавориты горожан.

«Какие виды транспорта вы предпочитаете?»

Относительно топовых позиций результат вполне ожидаем. В крупных городах предпочтительный вид транспорта — метро. Второе место у автобусов. Более трети москвичей пользуются электричкой. В Новосибирске ездят на маршрутках, а в Петербурге, помимо всего прочего, любят трамваи.

Интересным открытием стало, что половина опрошенных могут дойти до точки назначения пешком.

Следующим этапом стало выяснение слабых сторон 2ГИС. Мы пришли к пользователям с вопросом — чего нам не хватает?

«Чего не хватает в 2ГИС?»

Задачу с выбором конкретных видов транспорта мы решили с помощью недавно выпущенных фильтров, где пользователь может указать, каким видом транспорта он хочет воспользоваться. А вот вопрос «Когда приедет автобус?» остался актуальным для 64% опрошенных пользователей.

Именно в этот момент мы задумались о добавлении расписания движения общественного транспорта в 2ГИС и о том, как же все наши желания реализовать.

Где взять данные?

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

Да. К сожалению, данные устаревают, и это была вторая проблема, вставшая перед нами. Логичным и вполне очевидным решением было обратиться к тем, кто это расписание составляет и контролирует — в подведомственные учреждения. Зачастую конструктивный диалог начинался только через тернистый бюрократизированный путь и советов, вроде: «Пишите в Минтранс/Дептранс, а потом поговорим».

Нашли ответственного, начали диалог — полбеды.

Далее начинался марафон с:

  1. Объяснениями, что мы хотим и зачем нам это.
  2. Убеждениями, что наша задумка полезна для жителей и гостей города.
  3. Доказательством, что 2ГИС не монетизирует построение маршрутов с учётом периодичности движения.
  4. Заверениями, что это безопасно.

Самое курьёзное — техническая сторона вопроса, а в частности — формат передачи данных. Да, в каких-то городах есть автоматизированные системы по ведению расписания и API для доступа к этим данным (gtfs или передача в json в собственном формате), но это ждало нас далеко не везде. Где-то просто предлагали парсить сайт, опять-таки из соображений безопасности не предоставляя доступа к базам. Где-то были готовы выслать файлы (.xls, .doc, .pdf), но только один раз, без возможности своевременно обновлять информацию в нашем справочнике.

Первое место по оригинальности мы присвоили фотографии листочка бумаги с расписанием движения общественного транспорта.

А ведь изначально задачка казалась тривиальной — получить общедоступные данные от первоисточника!

Загрузка данных во внутреннюю систему

Получив доступ и загрузив к себе данные, мы встали ещё перед одной проблемой. Нельзя просто так взять и загрузить чужие данные во внутреннюю систему.

Почему?

Самое время рассказать, как внутри 2ГИС хранятся исходные данные. Все внутренние продукты для сбора и хранения информации мы разрабатываем сами. Софт для картографов (которые отвечают не только за карту, но и за транспорт) называется Fiji — подробный рассказ здесь (если кратко, то в Fiji картографы рисуют транспортный граф, вносят данные по общественному транспорту, хранят расписание. В систему уже внесены все собранные маршруты).

Первый анализ показал, что маршруты внутри нашей системы и у поставщиков различаются, причём местами — кардинально. Нужно было как-то сопоставить свои собственные маршруты и маршруты поставщика. Можно, конечно, сделать это вручную, но мы решили написать свой собственный матчер.

В качестве промежуточного формата для хранения выбрали GTFS, как уже общепринятый стандарт, плюс некоторые поставщики умеют выдавать расписание в этом формате. Для промежуточной БД, на которой работает матчер, выбрали PostgreSQL, а сам матчер написали для простоты на Python.

Матчить просто по типу и имени маршрута не получилось, так как маршруты очень сильно расходятся по именам у нас и у поставщиков. Матчить по названиям остановок не получилось по той же причине. В итоге матчер работает по достаточно сложной схеме, учитывая геометрию маршрута, тип транспорта и потом уже названия остановок и номера маршрутов.

При этом ошибки в сопоставлении всё равно есть, так как у поставщиков бывает очень большое количество направлений: отдельно на каждый будний день, отдельно на каждый выходной. Также возникают ошибки в сопоставлении кольцевых маршрутов, если они по разному заведены у поставщика и в нашей внутренней системе (Fiji).

Поэтому конечное решение-таки за человеком — картограф может вручную отменить сопоставление расписания, если поймет, что алгоритм отработал неправильно.

Алгоритм

Ядро алгоритма поиска написано на C++. На самом деле, поиск проезда на общественном транспорте это не один алгоритм, а несколько. Поиск прохода до ближайших остановок считается нашим алгоритмом пешеходной маршрутизации, который, в свою очередь, состоит из двух алгоритмов — «пиксельного» (с помощью которого мы строим проход по территории без графа дорог) и обычного (уже по пешеходному графу до остановки). В качестве же поискового алгоритма проезда между остановками у нас используется сильно модифицированный A*, в который мы добавили поддержку учёта расписания. И если раньше время ожидания транспорта на остановке было неким «среднестатистическим» временем для каждого проекта и каждого типа транспорта, то теперь учитывается или точное или интервальное расписание.

При этом в алгоритме пришлось учитывать много забавных нюансов в данных. Например, маршрут может иметь время отправления с остановки в 25 или даже в 47 часов. С точки зрения данных это значит, что это тот же рейс, что ходил в предыдущих сутках, и он просто ещё не завершил свою работу. Также нужно учитывать, что рейс может начать ходить «завтра» и, если пользователь ищет маршрут в конце текущих суток, то нужно заглядывать и в следующий день (актуально, если вы храните расписание по дням).

Отдельно решали проблему того, как комбинировать данные с расписанием и без расписания. В итоге решили, что маршруты без расписания по-прежнему участвуют в поиске, просто имеют меньший вес. При этом, если маршрут без расписания совпадает по остановочным платформам с маршрутом с расписанием, то мы его просто подклеим в выдачу, а если он идёт как-то по-другому, то это будет отдельный вариант проезда с меньшим весом, так как мы ничего не знаем про время ожидания на остановке.

Поскольку 2ГИС работает как онлайн, так и офлайн, то алгоритм работает и внутри приложения, и на сервере. Несмотря на то, что данные расписания более-менее статичны, серверный поиск у нас также используется, поскольку на медленных устройствах в случае наличия интернета запрос к серверу отработает намного быстрее, чем локальный поиск. Для серверного поиска у нас задействовано 8 поисковых бекендов, расположенных в трёх дата-центрах в Новосибирске, Москве и Дронтене (Голландия).

Релиз

Итоговый результат добавления расписания общественного транспорта в 2ГИС вы можете оценить в нашем мобильном приложении в Google Play и App Store. В веб-версии появится чуть позднее.

Зарелизившись, мы получили довольно много фидбэка. Проанализировав негативный, выделили две основные причины жалоб:

    Мы не рассказали пользователям должным образом, что в поиске проезда сейчас используется расписание и сломали привычные сценарии работы с приложением. При поиске маршрута вечером или ночью у пользователей пропали привычные маршруты в выдаче. Контрол выбора даты/времени поездки при построении маршрута выпал из сферы видимости.

📎📎📎📎📎📎📎📎📎📎