Планировщик маршрутов

Здравствуйте, дорогие читатели!

За окном вовсю сияет март, а мы уже начали готовиться к новому большому летнему путешествию (обязательно посмотрите предыдущее, если, конечно, ещё не видели его). К сожалению, идея проехать Соединённые Штаты поперёк накрылась медным тазом отложена до лучших времён. Но это не причина для уныния, ведь есть ещё сотни стран, требующих нашего внимания. И мы решили не заморачиваться и повторить прошлогодний опыт бэкпэкерства с InterRail, благо пол-Европы осталось неизъезженной.

Сказано — сделано. Набросали списочек городов для посещения и оказалось, что маршрут, в отличие от предыдущего года, не очевиден. В каком порядке их нужно объезжать, чтобы расстояние, преодолённое на поезде, получилось минимальным? Поиск нужных сервисов для составления маршрутов ничего не дал, а значит нужно написать свой! Что я и сделал.

Представляю вам планировщик маршрутов. Сервис довольно простой: вводишь начальный город, конечный, а также список городов посередине, — и получаешь оптимальный маршрут. Расстояния между городами считаются по прямой, поэтому результат оптимален только для самолётов. А для остального транспорта стоит учитывать, что дороги кривые и ездят по ним с разной скоростью. Но для того, чтобы прикинуть маршрут, информации достаточно. Конечно, между некоторыми пунктами дороги может вообще не существовать, но не беда: любой отрезок из пути можно исключить и система выдаст другой маршрут с учётом этого ограничения.

Проложить свой маршрут

Проложить свой маршрут

Для приготовления сервиса мне понадобились: Яндекс.Карты, AngularDart, Bootstrap. Туда пришлось добавить немного логики и свободного времени. Всё это было смешано, взболтано, вылито в высокий бокал и украшено методом ветвей и границ, прямо как учили в универе. Приятного аппетита.

Прошу опробовать и написать свои замечания и пожелания в комментариях. Исходники всего это дела можно увидеть всё там же — на GitHub.

Всегда к вашим услугам,
Редакция блога.

Как я браслет покупал

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

Jawbone UP Onyx

Jawbone UP Onyx

У нас такими браслетами торгуют только барыги предприниматели в барахолке Онлайнера. Стоимость $200. На сайте производителя же указана цена в $130. Правда доставка только в Штаты. Тоже мне проблема! Тут же выяснилось, что цена на сайте не включает налог. Пришлось заплатить чуть больше — $138. Посылка, видимо, помня, что Рождество близко, шла две недели вместо обещанной одной до службы пересылки и ещё полторы доупаковывалась для отправки. И уже после нового года она была отправлена на мой настоящий адрес. Это обошлось ещё в $23. Зато в Беларусь приехала очень быстро, всего за две с половиной недели (обычно посылки идут от четырёх недель).

Наконец в почтовом ящике обнаружилось уведомление, и я в предвкушении пошёл в свое почтовое отделение за игрушкой. Забрал, принёс — не работает. Не заряжается и вообще не подаёт никаких признаков жизни. Soft reset, hard reset — ничего не помогает. Посмотрел по форумам, написал в поддержку. Неделя переписывания со службой поддержки (приятные ребята) и уточнений — и ура, они выслали мне замену. Неделя до службы пересылки, неделя обработки, ещё $20 за доставку в Беларусь. На этот раз посылка приехала ещё быстрее: за две недели.

Забираю посылку, пробую включить новый браслет — та же беда. Не работает, не заряжается. Я совсем расстроился. Пишу снова в поддержку. Они меня там, видимо, недопонимают и вновь присылают инструкции, как сделать reset и запустить синхронизацию. Я попробовал ещё раз последовать этим инструкциям и ещё раз сделать reset, но уже без всякой надежды на успех. И каково же было моё удивление, когда браслет вдруг весело замигал огоньками. Как же так, ведь я делал всё то же самое много раз? Немного поисков и проблема обнаружилась: некачественный провод для зарядки.

Итого два с половиной месяца ожидания и $181. Зато у меня есть два работающих браслета и одна не очень-то работающая зарядка, но при определённом старании зарядить браслет можно. Правда один браслет придётся отправить производителю, потому что такие правила (не знаю, во сколько обойдётся отправка, жил бы в Америке было бы бесплатно). Зато они мне вышлют новую зарядку (где-то $15 за пересылку). То есть в результате я потратил больше времени и денег, чем если бы покупал сразу у нас.

Вот такая история.

И снова Dart

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

  1. Поддержка Dart в продуктах JetBrains просто отличная. Писать на Dart гораздо удобнее, чем на JavaScript, а ведь плагин для JavaScript разрабатывается и улучшается намного дольше. И всё это из-за более строгой структуры языка. Она позволяет IDE лучше просчитывать зависимости и в нужное время дополнять необходимые конструкции. Но не обошлось без ложки дёгтя. Иногда плагин просто перестаёт дополнять что бы то ни было, спасает только перезагрузка среды. И ещё не хватает привычных intentions, вроде склеить два if в один или заменить одинарные кавычки на двойные, но я думаю, что это будет реализовано со временем.

  2. В Dart есть приватные члены класса, но нет зарезервированного слова private. Всё потому, что все идентификаторы, начинающиеся с подчёркивания (_), считаются приватными. И это правильно.

  3. Видно, что язык разрабатывался с учётом опыта создания сложных приложений. Например, я нигде больше не встречал поддержки factory-конструкторов на уровне языка.

    class Singleton {
      static final Singleton _singleton = new Singleton._internal();
      factory Singleton() {
        return _singleton;
      }
      Singleton._internal();
    }
    
    var singleton = new Singleton();

    В этом же примере можно видеть ещё одну особенность Dart: именованные конструкторы. Так как в динамическом языке нельзя сделать перегрузку методов по типам параметров, то для конструкторов авторы решили добавить возможность выбора конструктора по имени. А для остальных случаев вполне хватает именованных необязательных параметров.

  4. В языке довольно много различного синтаксического сахара: тот же cascade operator (..). Крайне удобная штука для работы с DOM и стилями.

    element.style
      ..visibility = 'visible'
      ..display = 'block';
  5. Ещё прекрасно сделана подстановка значений переменных и выражений в строку. Это выглядит частью языка, а не afterthought, как, например, в PHP.

    previousLink.attributes['title'] += ' (${isMac ? '⌥←' : 'Ctrl + ←'})';

    Обращаем внимание на то, что внутри ${...} может быть любое выражение точно в таком же виде, в каком вы бы его увидели и без строки. Кавычки внутри выражения не закрывают строку, и их не нужно экранировать, что вполне логично, но в том же PHP этого нет.

  6. Dart — язык с необязательной типизацией. То есть если хочешь, можно указать тип переменной, а можно просто написать var и не париться. Всё это будет работать до тех пор, пока не попадётся, например, функция с указанным типом параметров. Вот тут-то тип твоей переменной будет проверен. И будет выведена ошибка, если типы не совпадают. Но когда вместо var указываешь реальный тип переменной, то проверки происходят гораздо чаще, буквально в каждом операторе, везде, где может возникнуть несовместимость типов.

    Кроме того, в Dart нет неявного приведения типов. Например, вот этот код выведет сообщение об ошибке потому, что нельзя просто так привести строку к булевому значению:

    String str = '';
    if (!str) {
      // do something
    }

    Но не стоит особо волноваться: о большинстве потенциальных проблем статический анализатор языка (то есть IDE) сообщит заранее.

    Все эти проверки работают в так называемом «checked mode». Чтобы этот режим включить, виртуальная машина должна быть запущена со специальным параметром, например:

    dart --checked main.dart

    Или в случае с сайтом сам браузер нужно запускать так (пример для Linux):

    DART_FLAGS='--checked' ./chrome

    Если этого не сделать, то виртуальная машина будет работать в production-режиме и ни одной дополнительной проверки не будет сделано. Зато выполняться скрипт будет очень быстро! Поэтому можно думать о типах, как об автоматических инструкциях assert в языке в помощь разработчику. Кстати, просто assert тоже присутствует и тоже не работает в production-режиме.

    А ещё в Dart есть Generics. И это позволяет создавать весьма сложные зависимости типов и опять же проверки. К сожалению, Generics можно применить только к классам, может, в будущем добавят поддержку отдельных функций.

    class ParseContext<S extends Iterable> {
      final S source;
    
      // More definitions
    }
  7. Переопределение операторов. Не думаю, что нужно рассказывать про плюсы и минусы этого решения. Все, кто когда-либо сталкивался с ними в любом другом языке, и так о них знают. Динамический Dart может добавить к этому ещё немного проблем. И хотелось бы иметь возможность создания произвольных операторов, как в Haskell. Было бы круто.

  8. Из недостатков можно выделить то, что интерфейсы визуально не отличаются от классов. То есть нет зарезивированного слова interface, вместо него используется тот же class. Но при этом есть слова и extends, и implements. Всё различие заключается в том, что может присутствовать в классе, но не может присутствовать в интерфейсе, и наоборот. К примеру, в интерфейсе может быть factory-конструктор, который будет возвращать реализацию этого интерфейса по-умолчанию. Но в этом случае не получится унаследоваться от такого интерфейса при помощи extends. Компилятор выдаст «The generative constructor expected, but factory found». А это не особо очевидно, особенно когда видишь это сообщение первый раз.

  9. Ещё один минус — размер js-файла на выходе. Пока не у всех есть браузер с нативной поддержкой Dart, и многим придётся загружать сконвертированный код. Ладно, будем честными: браузера пока ни у кого нет, кроме разработчиков, которые на Dart пишут (он называется Dartium, его можно скачать на сайте проекта). Так вот, сгенерированный JavaScript для этого блога весит 207 Кб (сравните с 8 Кб минифицированного Dart-кода). А всё потому, что в js-файл компилятору приходится встраивать всю ту огромную прослойку для поддержки разницы в DOM и событиях между языками.

Я думаю, что Google не оставит своих планов выпустить nextgen язык для Web. Меня лично эти планы вполне устраивают, так как я отлично представляю, чем этот язык будет лучше и удобнее. Как минимум он позволит выбросить весь тот backward-compatibility хлам, который уже давно никто не использует, но который обязан присутствовать в каждом браузере, потому что его могут использовать сайты, созданные 15 лет назад.

И не надо говорить, что всякие надстройки используют те, кто не осилил выучить нативный JavaScript.

P. S. К сожалению, нормальной поддержки подсветки Dart в блоге пока нет, но я надеюсь это в скором времени исправить. Исправил.

Рига

Уже довольно много времени прошло с предыдущего путешествия и насущная необходимость дальше расширять географию путешествий украла сон и похитила покой. Да и свеженькая виза жгла карман. Чтобы унять этот зуд, были приняты срочные меры и прикуплены билеты на автобус в соседнюю страну (Ecolines, ≈39 € в обе стороны на персону).

Ехали ночью. Приехали в 6 утра и решили попытать счастья в гостинице: вдруг нас пустят раньше положенных 14:00. И пустили же, и даже не взяли дополнительных денег, за что им отдельное спасибо. Дополнительные 3 часа сна нам очень пригодились, без них всё было бы совсем по-другому.

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

Старый город
Читать далее...
Песни про расставания

Одна из моих любимых команд на YouTube (я их уже упоминал) выложила специально ко дню святого Валентина две подборки песен о том, как люди переживают расставания с любимыми. Хочу с вами этими подборками поделиться, ведь всегда интересно посмотреть, как мотивы меняются с течением времени.

Итак, мужчины:

History of Men Moving On

И женщины:

History of Women Moving On

И что мы видим? Чем ближе к настоящему времени, тем женщины становятся всё более независимыми, а мужчины начинают больше крыть матом.

Любите друг друга.

P. S. Так уж получилось, что это юбилейный двухсотый пост. Будем надеяться, что блог проживёт ещё как минимум пять раз по столько.

← СтаршеМоложе →