/flyer

Primary LanguageClojureEclipse Public License 1.0EPL-1.0

Flyer

🚀 Uma aplicação para determinar a rota com o melhor preço entre dois aeroportos. 🚀

Clojure Java Java

Tabela de conteúdos

Instalação

Para executar a aplicação, você pode optar pelas seguintes formas:

  • Clonar este repositório git clone https://github.com/YuhriBernardes/flyer.git
  • Baixar o arquivo compilado na aba de releases.

Utilização

Para executar o programa é necessário um arquivo CSV. Nesse arquivo, cada linha representa uma rota entre dois aeroportos, onde o primeiro item é a origem da rota, o segundo é o destino e o terceiro item é o custo da viagem.

OBS: O arquivo CSV não deve conter cabeçalho

GRU,BRC,10
BRC,SCL,5
GRU,CDG,75
GRU,SCL,20
GRU,ORL,56
ORL,CDG,5
SCL,ORL,20

Executar diretamente

Tendo o clojure instalado na máquina, rode o comando:

$ clojure -m flyer.main <arquivo-de-entrada>

Executar pelo java

Executando o arquivo compilado:

$ java -jar flyer.jar <arquivo-de-entrada>

Caso não tenha baixado o arquivo compilado (flyer.jar), execute os commandos abaixos.

Gerar Uberjar:

$ clojure -A:uberjar

Testes

Rode o comando a seguir:

$ clojure -A:test -m kaocha.runner

Documentação

Resumo

Ao inicializar a aplicação, estarão disponíveis duas interfaces para operação. Uma diretamente pelo console e outra via API REST.

Observações

  1. Por padrão, o servidor WEB utiliza a porta 3000
  2. É obrigatório mandar via headder o "Content-Type"

Iteração via console

Dada a inicialização da aplicação, será exibida uma mensagem solicitando que entre com a origem e destino desejadas para que possa ser calculada a rota de menor preço. A entrada fornecida deve atender ao padrão <origem>-<destino> (exemplo: "GRU-CDG").

Exemplo

Please enter the route: GRU-CDG
Best route: GRU - BRC - SCL - ORL - CDG > $40,00

Iteração via API Rest

Para iteração via API é fornecido um endpoint na rota /route com os métodos GET e POST disponíveis. Com eles é possível obter rotas e cadastrar novas escalas. Documentação da API também disponível via:

Cadastro de novas escalas

Endpoint: /route Método: POST Formato: application/json

Retornos

  • Status 201 = Criado com sucesso

Corpo da requisição*

{
 "origin": "string",
 "destination": "string",
 "value": 0
}

onde origin é a origem da escala, destination é o destino da escala e value é o custo para realizar a escala.

Exemplo de requisição

curl --request POST \
  --url http://localhost:3000/route \
  --header 'content-type: application/json' \
  --data '{"origin": "A",
 "destination": "B",
 "value": 12.2
}'

Cadastro de novas escalas

Endpoint: /route Método: POST Formato de retorno: application/json Parâmetros de busca (query): origin = origem | destination = destino

Retornos

  • Status 200 = Sucesso
  • Status 404 = Não foi encontrada nenhuma rota

Corpo do retorno da requisição

{
 "path": ["string"],
 "value": 0
 }

onde path é um vetor com a sequência de escalas que deve ser realizada e value é o valor total do trajeto.

Exemplo de requisição

curl --request GET \
  --url 'http://localhost:3000/route?origin=GRU&destination=CDG'

Estrutura de pastas

Código fonte

./flyer/src
└── flyer
    ├── console
    │   ├── io.clj
    │   └── main.clj
    ├── core
    │   ├── dijkstra.clj
    │   ├── file.clj
    │   ├── graph.clj
    │   ├── operations.clj
    │   └── path_finder.clj
    ├── main.clj
    └── server
        ├── common_interceptors.clj
        ├── configuration.clj
        ├── main.clj
        └── routes
            └── route.clj

5 directories, 12 files

Testes

./flyer/test
├── flyer
│   ├── console
│   │   └── io_test.clj
│   ├── core
│   │   ├── dijkstra_test.clj
│   │   ├── file_test.clj
│   │   ├── graph_test.clj
│   │   ├── operations_test.clj
│   │   └── path_finder_test.clj
│   └── server
│       ├── common_interceptors_test.clj
│       ├── configuration_test.clj
│       └── routes
│           └── route_test.clj
├── test-resources
│   └── input-sample.txt
└── test_utils
    └── file.clj

7 directories, 11 files

Decisões de design

Dado que a aplicação disponibiliza duas interfaces para utilização (API REST e console), foi optado por isolar a camada que detinha as regras e operações para que esta seja consumida pelas interfaces. Desta forma, todos os processos relacionados às regras de negócio foram alocadas na pasta core e para cada interface foi criado um pacote isolado (server e console).

Melhorias

  1. Por padrão, considerar os corpos das requisições como application/json.
  2. Possibilitar a configuração da porta na qual o web server será disponibilizado.
  3. Melhorar o isolamento das operaçòes de I/O.
  4. Realizar testes funcionais da aplicação (hoje há somente testes unitários).
  5. Disponibilizar aplicação via Docker.
  6. Traduzir este documento para ingês.

License

Copyright © 2020 Yuhri

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.