An open API service indexing awesome lists of open source software.

https://github.com/rcv911/assisted_team_test

Простенький веб сервис, показывающий полезную инфу по перелётам. Основная логика построена на парсинге xml файлов.
https://github.com/rcv911/assisted_team_test

aiohttp aiohttp-rest-api aiohttp-server docker docker-compose xml-parsing

Last synced: 25 days ago
JSON representation

Простенький веб сервис, показывающий полезную инфу по перелётам. Основная логика построена на парсинге xml файлов.

Awesome Lists containing this project

README

          

# assisted_team_test
Простенький веб сервис, показывающий полезную инфу по перелётам, а также
разницу между двумя файлами. Основная логика построена на парсинге xml файлов.

## Задача

Есть два XML – это ответы на поисковые запросы, сделанные к одному из
партнёров. В ответах лежат варианты перелётов (тег `Flights`) со всей
необходимой информацией.

Нужно сделать вебсервис, в котором есть эндпоинты, отвечающие на следующие
запросы:

* Какие варианты перелёта из DXB в BKK мы получили?
* Самый дорогой/дешёвый, быстрый/долгий и оптимальный варианты
* В чём отличия между результатами двух запросов (изменение маршрутов/условий)?

Язык реализации: `python3`.
Формат ответа: `json`.
Используемые библиотеки и инструменты — любые на выбор.

### Описание

API со следующим набором эндпоинтов:

• /v1/parse?parameters - Получение вариантов (дорогой/дешёвый,
быстрый/долгий и оптимальный) перелёта
из DXB в BKK

• /v1/diff - Симметричная разница между двумя файлами

Сервис работает на ``python 3.7``.

Фреймворк для написания API — ``aiohttp``.

Библиотека для создания простенького REST API ``aiohttp_rest_api``
Документация: [https://aiohttp-rest-api.readthedocs.io/](https://aiohttp-rest-api.readthedocs.io/)

Конфиг приложения находится: [/config/config.toml](config/config.toml)

## Getting started
Для запуска необходимо выполнить команду: `docker-compose up -d`

После запуска раскатится docker контейнер:

• Контейнер веб приложения на http://127.0.0.1 по умолчанию

Файл [PostmanCollection](assisted_team_test.postman_collection.json) содержит
примеры запросов на все API, который можно импортнуть в Postman

## Подробнее об методах API
## v.0.1.0

• GET http://localhost/v1/parse?need_return=&action=

need_return:
true - парсит файл RS_Via-3.xml с обратным направлением (параметр по умолчанию)
false - парсит файл RS_ViaOW.xml без обратного направления

action:
cheap - варианты полётов, начиная с самого дешёвого билета (параметр по умолчанию)
fast - варианты билетов, начиная с самого быстрого перелёта
expensive - варианты полётов, начиная с самого дорогого билета
slow - варианты билетов, начиная с самого медленого перелёта
optimal - оптимальные варианты билетов

• GET http://localhost/v1/diff

## v.0.1.1

• GET http://localhost/v1/onward_diff?option=

option:
1 - сравнивает файл RS_Via-3.xml с RS_ViaOW.xml по тегу OnwardPricedItinerary
2 - сравнивает файл RS_ViaOW.xml с RS_Via-3.xml по тегу OnwardPricedItinerary

- Идея парсинга ``/v1/parse`` заключается в первоначальной имитации выбора пользователя.
Из условия задачи мне известно: пункты назначения, дата, два файла на выбор
с необходимой информацией. Вилкой логики служит имитация выбора пользователем
обратного направления (параметр ``need_return``). Не вижу смысла на
один запрос пользователя скачивать сразу два файла вариантов билета, при условии,
что партнёр гарантирует предоставить всю необходимую информацию. Это
просадка по производительности, а также не стоит забывать о том, что у меня
не один партнёр по предоставлению информации о перелётах (но это уже за рамками
текущей задачи). Мне достаточно попросить пользователя указать необходимость
обратного билета, либо же сделать по умолчанию не брать в расчёт обратное
направление.

- Собранные варианты перелётов учитывались из соображения - что для удобства
пользователя лучше? Конкретно для меня важны параметры времени и цены. ``cheap``
покажет варианты билетов, начиная от самого дешёвого, но и в то же время быстрого по
времени, если цены одинаковые. ``fast`` покажет варианты билетов, начиная от самого
быстрого, но и в тоже время наиболее дешевого при одинаковом времени.
``expensive`` покажет варианты билетов, начиная от самого
дорогого, но и в тоже время наиболее быстрого по времени, если цена одинакова.
``slow`` покажет варианты билетов, начиная от самого
медленного перелёта, но и в тоже время наиболее дешёвого, если время перелёта
совпадает. Интересный выбор ещё ``optimal``, который совпадает с вариантом
``fast``. Почему так и почему бы не зашиться на прямые перелёты и не выделить
этот вариант в отдельную сортировку выборки данных?
Если подумать логически, то я не встречал быстрых непрямых перелётов.
Учитывая поведение пользователя, то он глянет максимум 5 вариантов, а может и
меньше.

---

- Идея показа разницы между файлами ``/v1/diff`` основана на симметричной разницы
тегов и аттрибутов файлов. Теги укажут на то, какого узла иерархии не хватает.
Например, узла с информацией об обратных билетах ``ReturnPricedItinerary``.
Атрибуты укажут разницу между перевозчиком ``Carrier``. Перевозчик, на самом деле,
очень важный параметр, особенно, если он является участником крупного
международного альянса как свидетельства об авиационном здоровье. Также разница
может быть и в отсутствии каких-либо тарифов в ``ServiceCharges``, например, информация о стоимости
билета для ребёнка ``SingleChild``.

---

- ``/v1/onward_diff`` - отличия между файлами по тегу ``OnwardPricedItinerary``.
Необходимо было привязать уникальность к данным. Отправная точка ``DXB`` для всех одинакова,
поэтому можно прицепиться к отправному билету сравниваемого файла и сделать уникальный
ключ ``key = '{ID перевозчика}-{номер рейса}'``. Это позволить разделить данные и установить
порядок следования объектов для сравнения. Почему такая необходимость возникла?
Количество элементов в файлах может отличаться, некорректные данные могут находиться
в одном из файлов (или же в обоих).

- Полезная информация хранится в ``['differences'][key]['difference']``, где как раз указаны различия
между билетами (время, номер рейса, перевозчик, класс, тип билета и т.д.).
Например:

Различия (показывают, что изменилось во 2-ом файле)

```json
{
"text": "Bangkok Airways",
"ArrivalTimeStamp": "2018-10-28T0715",
"FlightNumber": "4330",
"FareBasis": "2820303decf751-5511-447a-aeb1-810a6b10ad7d@@$255_DXB_BOM_535_6_16:10_$255_BOM_BKK_4330_77_01:35__A2_1_1",
"id": "PG",
"Class": "Y",
"DepartureTimeStamp": "2018-10-28T0135"
}
```

Билет, который надо сравнить
```json
{
"FlightNumber": "70",
"Source": "BOM",
"Destination": "BKK",
"DepartureTimeStamp": "2018-10-23T0840",
"ArrivalTimeStamp": "2018-10-23T1440",
"Class": "V",
"NumberOfStops": "0",
"FareBasis": "2820231f40c802-03e6-4655-9ece-0fb1ad670b5c@@$255_DXB_BOM_535_6_15:10_$255_BOM_BKK_70_6_08:40_$255_BKK_BOM_61_6_08:55_$255_BOM_DXB_544_6_18:50__A2_0_0",
"WarningText": null,
"TicketType": "E",
"id": "9W",
"text": "JetAirways"
}

```
Билет, с которым сравнивают

```json
{
"FlightNumber": "4330",
"Source": "BOM",
"Destination": "BKK",
"DepartureTimeStamp": "2018-10-28T0135",
"ArrivalTimeStamp": "2018-10-28T0715",
"Class": "Y",
"NumberOfStops": "0",
"FareBasis": "2820303decf751-5511-447a-aeb1-810a6b10ad7d@@$255_DXB_BOM_535_6_16:10_$255_BOM_BKK_4330_77_01:35__A2_1_1",
"WarningText": null,
"TicketType": "E",
"id": "PG",
"text": "Bangkok Airways"
}

```

Также для удобства восприятия в ``['differences'][key]['ticket']`` - билет(ы), который сравниваем и
``['differences'][key]['new_ticket']`` - билет(ы), с которым сравниваем.

Имеются ещё
``['new_tickets']`` - где хранятся новые билеты или же не вошедшие в сравнение (из сравниваемого файла)
и ``['wrong_tickets']`` - где показаны некорректные данные (неправильная отправная точка ``DXB``).
Оба не несут информативной ценности, логику лишь загружают, но выведены для показа.

### Локальный запуск приложения

Настрока через PyCharm:

![local_debug](images/local_debug.jpg)

### Мысли об улучшении и проблемы, с которыми столкнулся

- Проблема дубликата тегов ``Flights``. Пришлось накручивать кастомную логику
по фильтрации

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

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

Мысли об улучшении:

- Необходимость в улучшении или изменении логики сортировки. Сейчас она выглядит
по нубски. Но в рамках MVP - сортировка работает.
![flake8](images/flake8.jpg)

- Хардкод на два файла, можно изменить код и сделать более универсальным.

- Можно добавить дополнительные параметры, например, длительность пересадки. \
Фильтрацию по тарифу.

- Возможно стоит прикрутить ``pytest``.