Итак, мы добрались до последнего блока финальной задачи коричневого и черного поясов. В частях с "R" по "T" вам понадобится добавить поддержку справочника организаций наряду с транспортным справочником. В части "R" вам понадобится просто добавить возможность поиска организации по некоторым условиям, а именно: вам будут даны организации, которые есть, скажем, в том же городе, в котором ходят эти самые автобусы. Организация задается протобуфным сообщением "Company", в этом сообщении есть разные поля, но из них пока будут использоваться только четыре, а именно: это названия организации, это телефоны организации, это URL-адреса организации и рубрики, ну, то есть условно типы какие-то этой организации. Как вы видите, "Name", "Phone" и "Url" это тоже некоторые протобуфные сообщения. Это, соответственно, название содержит в себе строковое "value", строковое значение и какой-то тип этого названия, который нам сейчас на самом деле не пригодится. Это главное название, это синоним или это короткое название — сейчас неважно, главное только строковое значение. Это "message Name". А "message Phone" описывает номер телефона, причем для вашего удобства он будет уже [inaudible] , то есть он будет разложен на компоненты. Ну, вот вы видите, какие там есть компоненты. Опять же, что вам нужно будет использовать, — это тип этого номера телефона, это именно телефон или это факс, это код страны, код города, собственно сам номер телефона, который в России семизначный и добавочная часть. И это все будут строки. Это как раз то, что вам понадобится использовать. И наконец, "Url" — это просто строковое значение. И вот вам будут даны организации, и нужно будет искать среди этих организаций по каким-то условиям, по условиям на эти самые четыре свойства. Ну, а рубрики, соответственно, это будут некоторые числовые значения и отдельно будет дан маппинг преобразование этих чисел в какие-то нормальные названия, условно, парки, кафе, санатории и так далее. Ну и, давайте, рассмотрим небольшой пример. Вот, допустим, у нас есть две организации, два парка, два сочинских парка. Первый парк "Дендрарий". У него есть два каких-то номера телефона и какой-то интернет-адрес. И есть парк "имени Фрунзе", у которого нет номера телефона, нет никакого интернет-адреса, просто приходите и гуляйте. И нужно как-то уметь искать по этим организациям. Первый пример запроса — название организации "имени Фрунзе". Конечно, только одна организация, вторая — имеет название "имени Фрунзе", соответственно, нужно сказать, что вот, только вторая организация подходит под этот запрос. Второй пример запроса: меня интересуют парки и санатории, вообще, во всем Сочи. И поскольку у меня две организации, обе парки, они обе подходят, вот соответственно, запрос ответ, на который это две организации. Другой пример, чуть более сложный: бывают условия на несколько свойств сразу, в данном случае меня интересуют организации, у которых указанные номера телефонов 267-18-42 и 267-18-43, один из них хотя бы должен быть у данной организации, и обязательно интернет-адрес dendrarium.ru. Вот такой запрос в последней колонке означает, что меня интересуют организации, у которых один из номеров телефона подходит под один из указанных, из тех двух указанных 18-42, 18-43 и интернет-адрес такой, как я сказал. С интернет-адресом все понятно, просто строково сравниваем и все, с номерами телефонов придется немножко помучиться, потому что, когда я говорю, что меня интересуют номера телефонов 267-18-42 и 18-43, я говорю, что меня как будто бы не важен код страны и код города, ну, и это тоже нужно будет учесть. Но, в данном случае, действительно у "Дендрария" второй телефон подходит под заданные условия и URL-адрес тоже подходит, и поэтому "Дендрарий" можно вывести как результат ответа на этот запрос. Ну и, в общем-то, с частью "R" получается все, вам просто нужно реализовать запрос поиска по организациям. В части "S" мы наконец полноценно совместим транспортный справочник и справочник организаций, и вам понадобится строить маршрут до организации. При этом условия на организации будут задаваться в том же формате, что и в части "R", в виде условий на свойства организаций. Ну, вот о чем собственно речь? Вот у нас есть автобусы, плюс у нас есть организации, вот в данном случае парк "имени Фрунзе" и парк "Дендрарий". Теперь для организаций мы будем знать, какие ближайшие автобусные остановки, от которых можно до них дойти и расстояние пешком от этих остановок до этих организаций. Ну вот, например, до парка "Дендрарий" имеет смысл идти только от остановки "Цирк" и это 180 метров, а до парка "имени Фрунзе" можно идти от трех остановок: от "Театральной", от "Пансионата Светлана" и от "Цирка". Ну, и есть, соответственно, какие-то расстояния. И получается, наш граф увеличивается, становится более интересным и по нему можно строить маршрут. Сам запрос, маршрут до организации, "RouteToCompany", имеет простую структуру, на вход подается остановка, от которой я хочу доехать и фильтр на организации, до которых я хочу доехать. Например, я хочу доехать от "Мацесты" до какого-нибудь парка. И вот такую задачу пользователя нашей большой красивой системы мы должны научиться решать. На выходе просто маршрут, примерно в том же формате, что и раньше, но добавятся некоторые дополнительные истории. Как отвечать на этот запрос? Для начала нужно будет с помощью того кода, который вы напишете в части "R", найти организации, которые подходят под данный запрос, затем выбрать ближайшую из этих организаций, построить маршрут и нарисовать этот маршрут, от остановки до организации. Что делать с самими организациями и как их рисовать? Вот та карта, которая была до этого, вам ее рисовать не придется, вам нигде не придется рисовать сразу все организации на карте. Вам понадобится рисовать только маршрут от остановки до организации. Момент первый: вам нужно будет точно так же, как вы для остановок выбирали координаты на схеме, точно так же для организации нужно будет выбрать координаты на схеме. Это нужно будет сделать в самом начале для всех организаций и поэтому итоговая схема будет не совсем такая, какой она была в части "N", например, потому что для организации тоже выбираются координаты, точно теми же сжатиями координат, с кликами и всем прочим. Соответственно, схема получается вот такой с учетом организаций, она же будет подложкой для схемы маршрута. И здесь видно, например, что от "Театральной" до "Пансионата Светлана", между двумя крайне левыми остановками расстояние больше, чем между другими, больше, чем оно было раньше. Почему? Потому что, на самом деле, там еще есть парк "имени Фрунзе", для которого мы тем же алгоритмом, что и раньше навычисляли координату. И парк "Дендрарий" где-то вот там расположен, у него такой же "X", как у остановки стадиона, такой же "Y", как у "Пансионата Светлана". Но, опять же, это мы все повычисляли, мы учли, что парк "имени Фрунзе" соседний с тремя остановками, что парк "Дендрарий" соседний с одной остановкой, это мы учли при склейках всевозможных, которые вы уже написали. Но сами организации по умолчанию рисоваться не будут, изначально будет вот такая схема. И собственно, как будет выглядеть маршрут? Вы рисуете подложку с учетом всего расположения остановок, но по алгоритму из части "М" еще. Дальше вы хотите нарисовать маршрут. Как это происходит? Вы рисуете большой полупрозрачный белый прямоугольник и на нем рисуете маршрут, сначала вы рисуете, собственно, в зависимости от того, каким задан порядок слоев, вы рисуете линии автобусов, через которые проходит маршрут, вы рисуете черную линию от конечной остановки маршрута до организации, в данном случае до "Дендрария" маршрут получился, вы рисуете названия автобусов на конечных, через которые вы пересаживались, вы рисуете промежуточные остановки, эти самые белые круги, вы рисуете черный круг для организации, до которой вы доезжаете, рисуете названия остановок и названия организаций. И вот именно эта картинка будет выхлопом запроса "RouteToCompany" в части "S". Наконец в части "Т" в виде кульминации вам понадобится учесть время работы этих самых организаций, то есть не имеет смысла приезжать в парк "Дендрарий" ночью, потому что он закрыт и вот это нужно учесть. Соответственно, для всех организаций, в данном случае, для парков, добавится время работы. Вот "Дендрарий" работает ежедневно с 9:00 до 17:00 зимой, а парк "имени Фрунзе" работает ежедневно и круглосуточно. Бывают еще разные способы создать времена работы. Это вы все подробно прочтете в условии, ну, например, можно сказать, что время работы ежедневно с 8:00 до 15:45 и с 17:00 до 23:00, то есть бывает перерыв на обед, это тоже допустимо, это тоже описывается. Бывает, что организация работает ночью, с десяти вечера до пяти утра. Но это задается, как промежуток с 0:00 до 5:00 и с 22:00 до 24:00. Тоже нормально. Можно задавать ограничения на дни недели, например, работать по вторникам и средам с 10:00 до 17:00, такое тоже можно. И вот, последний, четвертый пример справа, что можно работать, иметь разный режим работы в будни и в выходные, например, в будни с 10:00 до 20:00, а выходные с 11:00 до 16:00. Это все будет задаваться и это все вам нужно уметь обрабатывать. И давайте рассмотрим пару небольших примеров. Пусть вам нужно построить маршрут от остановки "Мацеста", вот там справа внизу, до любого парка и начать в 8:30. Понятно, что в данном случае все две организации подходят под условие "Парк". Нам нужно найти ближайшую из них с условием на то, что не все работает всегда. В данном случае наиболее оптимальный маршрут — это маршрут до парка "Дендрарий", он займет, по сути, 25 минут 49 секунд. Вы приедете туда за четыре минуты 11 секунд до открытия и вам ничего не стоит дождаться открытия и пойти гулять в "Дендрарий". Суммарный маршрут займет 30 минут с учетом ожидания открытия организации. А, если вы поедете от той же остановки, от "Мацесты", но в восемь утра, тогда вам придется слишком долго ждать открытия "Дендрария" и проще доехать до парка "имени Фрунзе" и погулять там. Вы приедете туда в 8:33:05 секунд, ждать открытия не нужно и такой маршрут займет 33 минуты и пять секунд. Ну и, соответственно, в части "Т" вам нужно будет учесть время работы организации, построить маршрут с учетом этого. Итоговая структура маршрута получается следующей: вы ждете автобуса, это то самое ожидание автобуса, которое дается в конфиге, вы едете на автобусе, с учетом того, сколько остановок ехать, с учетом расстояния между остановками. Вы, возможно, пересаживаетесь, возможно снова ждете автобуса, снова едете. Когда вы доехали до конечной, до конца вашего маршрута, вы идете пешком до организации. Это тоже занимает какое-то время с учетом скорости пешехода и расстояния от остановки до организации. И, наконец, возможно вы ждете открытия этой организации. Вот такой структуры маршрут вам и нужно будет вывести в части "Т". И на этом финальная задача закончится.