30 июл. 2015 г.

Эмулятор автомобильного движения на akka

Хотел давно освоить интересный фреймворк akka. Akka реализует концепцию акторов на языке scala, хотя API у него есть как и на scala, так и на java. В двух словах концепция акторов подразумевает, что есть акторы (актеры), которые параллельно выполняют какие либо операции, создают новых акторов, а общаются с другими акторами с помощью сообщений. Все как у людей. Испробовать все это я решил на автомобильном эмуляторе.
Фреймворк, хоть и написан на scala, имеет API на java, которым я и воспользовался. На официальном сайте есть понятная документация на английском языке.

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

Немного подумав я набросал следующую систему, которая будет всем этим управлять.


Начну с клиента, клиент в браузере по кнопке должен добавлять автомобиль, каждые n секунд происходит смена обстановки на дороге, которая тут же отправляется клиенту. Для этого я применил технологию веб-сокетов, которая, кстати, с помощью spring boot удивительно легко настраивается. Клиент и Сервер по сути являются равноправными участниками обмена информацией. Для того, чтобы отобразить актуальную обстановку на дороге не нужно каждый n секунд ходить на сервер и смотреть, поменялось ли что, сервер сам уведомит.

Теперь непосредственно об акторах. Я считаю, что создал довольно естественную модель:

ManagerActor — создает все другие акторы в начале. Если добавляется новый автомобиль, то он создает его.

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

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

RoadActor — Дорога. Получает ходы автомобилей и обновляет состояние дороги. Далее отправляет новое состояние дороги ViewActor и всем автомобилям (через DecisionActor)

ViewActor — Глаза. Преобразует дорогу в удобный для клиента вид.

Основная логику приложения выполняют акторы, представляющие автомобили.

Каждому автомобилю я дал три параметра:

  • Желаемая скорость (1, 2 или 3)
  • Вежливость
  • Наглость (может не совсем удачное название)
Первый параметр означает скорость, с которой будет ехать автомобиль если у него не будет спереди помех.

Второй параметр (вежливость) является вероятностью того, пропустит ли автомобиль другой автомобиль в свой ряд если тот попросит.

Третий параметр (наглость) является вероятностью того, что автомобиль не постесняется попроситься в ряд, если ему будет хотеться перестроится.

После начала каждого хода каждый автомобиль получает дорожную карту и создает для себя стэк возможных перемещений. На вершине стэка должно находится самое выгодное перемещение, на дне стэка самое невыгодное перемещение (остаться на месте).  Затем самое выгодное решение отправляется в центр решений. Центр решений принимает все ходы, если отправляется ход, приводящий к аварии, то ход автомобиля, который не имеет преимущества аннулируется и ему отправляется сообщение об этом, которое содержит ссылку на автомобиль-конкурент.

Если автомобиль получает сообщение об аннуляции его хода, у него есть несколько вариантов:

  • Взять еще один ход из стека и заново сходить. 
  • Попросить автомобиль-конкурент переходить и заново сходить этим же перемещением.
В свою очередь автомобиль конкурент при получении запроса на «уступить» может отказать, а может и согласиться.

Также надо уметь «разруливать» ситуации, когда более двух автомобилей претендуют на одно и то же место.

Я реализовал это все. Проект на гитхабе. Хоть это и веб приложение, но пока считается, что клиент у этого веб приложения один. Хотя за 5 мин можно сделать этот сервис многопользовательским. (Создавать несколько ManagerActor и вещать по разным URL, а не по одному, как сейчас).

В браузере это выглядит так.


Настраивается генератор, который в начале дороге генерирует автомобили c определенными параметрами.  Генератор может генерировать автомобильное движение с различной плотностью. Кликнув на любое место дороги можно поставить туда сломанный автомобиль (препятствие). Ну и наблюдать на то, как все происходит. ИМХО похоже на наши дороги:)

 (да, графике время не уделял, все схематично)

Проект на гитхабе


Комментариев нет :

Отправить комментарий