# challenge-gamersclub
Este repositório contém parte (Backend) da solução para o desafio da Gamersclub.
## TOC
- [Observações](#Observações)
- [Testes e cobertura](#Testes-e-cobertura)
- [Desenho da arquitetura](#Desenho-da-arquitetura)
- [Modelagem de dados](#Modelagem-de-dados)
- [Instalação](#Instalação)
- [Configuração](#Configuração)
# Observações
Para não gerar ruídos no entendimento, na fase de grupos as equipes se confrontam em jogos de ida e volta. O outro ponto, é que fixei o escopo em um simulador de torneio. Logo, o banco em produção ou desenvolvimento é populado inicialmente com algumas informações como: torneio, rounds, grupos e equipes. E no momento que uma requisição é enviada, ele gera as partidas e atualiza as devidas pontuações. Mas ressalvo, que se fosse para sempre criar um novo torneio, rounds, grupos, equipes e etc... A cada nova requisição, também não seria complicado de fazer, na verdade ficaria até mais simples pro meu lado.
# Testes e cobertura
A API possui testes de unidade e integração que cobrem **93,66%** do código. Isto pode ser convertido em uma confiabilidade de que há apenas **6,34%** de chances de liberação de bugs, caso ocorressem novas manutenções nesse desafio.

# Desenho da arquitetura

# Modelagem de dados

# Instalação
Requisitos:
* [NodeJS](https://nodejs.org/en/)
* [Yarn](https://yarnpkg.com/en/)
* [Docker](https://docs.docker.com/compose/install/)
O Yarn foi escolhido por conta do avançado sistema de cache, entretanto, pode ser utilizado com o npm padrão.
``` bash
yarn
```
Após a instação das dependências, deve-se executar o comando para subir a infraestrutura da API (MariaDB, se for o caso. É possível manter o ambiente de desenvolvimento com o SQLite).
No diretório raiz do projeto (Para o MariaDB)
```bash
sudo docker-composer up
```
Quando a infraestrutura já estiver operacional, execute as migrations.
``` bash
yarn sequelize db:migrate
```
Após a execução das migrations, popule o banco com as informações iniciais necessárias.
``` bash
yarn sequelize db:seed:all
```
Para rodar o servidor em ambiente de produção
``` bash
yarn start
```
Executar o comando para rodar o servidor em ambiente de desenvolvimento.
``` bash
yarn dev
```
Executar o comando para depurar a aplicação em ambiente de desenvolvimento.
``` bash
yarn debug
```
Executar o comando para rodar os testes de unidade e integração.
``` bash
yarn test
```
## Uso
.luiz-ricardo-1/
├─ .circleci
├─ \_\_tests\_\_
├─ data
├─ docker
├─ src
├─── app
├─── config
├─── database
├─── errors
├─── helpers
├─── routes
└─── services
A seguinte estrutura é descrita:
* **.circleci/** -> diretório onde ficam os arquivos .yml para configuração do CI/CD.
* **\_\_tests\_\_/** -> diretório onde ficam os testes unitários e de integrações.
* **data/** -> diretório que contém arquivos temporários dos bancos de dados MariaDB ou SQLite.
* **docker/** -> diretório que contém configurações e scripts para inicializar containers do Docker.
* **src/** -> diretório que contém todo o código fonte da aplicação (Podendo ser utilizado pelo Webpack para gerar o `dist`.
* **app/** -> diretório que contém a regra de negócio da API, como controllers, models e middlewares.
* **config/** -> arquivos em JS que fazem o setup de dependências chaves para o correto funcionamento da aplicação.
* **database/** -> migrations, seeders e hooks.
* **errors/** -> arquivos em JS que representam exceções da aplicação.
* **helpers/** -> arquivos em JS que contém funções auxiliares para várias funcionalidades.
* **routes/** -> arquivos em JS para realizar o mapeamento das rotas.
* **services/** -> abstrações de integrações com serviços externos como por exemplo: Elastic Search, Firebase, etc.
# Configuração
Realizar cópias do .env.example.
``` bash
cp .env.example .env
cp .env.example .env.test
```
## Variáveis de ambiente
| Variável | Descrição |
|:----------:|:-------------:|
| APP_ENV | Ambiente da aplicação, podendo ser *development*, *testing*, *staging* ou *production*. |
| APP_SENTRY_DSN | Callback do Sentry para o envio de exceções/logs. |
| DB_USERNAME | Usuário do banco de dados. |
| DB_PASSWORD | Senha do banco de dados. |
| DB_DATABASE | Nome do banco de dados. |
| DB_HOST | Endereço do banco de dados. |
| DB_DIALECT | Tipo de banco de dados que será utilizado pelo Sequelize. |
| DB_STORAGE_SQLITE | Adaptador para ser utilizado na persistência dos dados no SQLite (Para desenvolvimento e testes automatizados). |
| DB_OPERATORS_ALIASES | Permitir o uso de apelidos para operações de busca.
**Nota: Com o ambiente da aplicação (APP_ENV) definido como *development*, serviços externos como Sentry serão desabilitados.**
### Variáveis de ambiente sugeridas para ambiente de desenvolvimento
###### .env
```env
APP_ENV=development
APP_SENTRY_DSN=
DB_USERNAME=root
DB_PASSWORD=
DB_DATABASE=gamersclub
DB_HOST=localhost
# Dialect Options -> sqlite | mariadb
DB_DIALECT=sqlite
DB_STORAGE_SQLITE=./data/sqlite/database.sqlite
DB_OPERATORS_ALIASES=false
```
###### .env.test
```env
APP_ENV=development
APP_SENTRY_DSN=
DB_USERNAME=root
DB_PASSWORD=
DB_DATABASE=gamersclub
DB_HOST=localhost
# Dialect Options -> sqlite | mariadb
DB_DIALECT=sqlite
DB_STORAGE_SQLITE=./__tests__/database.sqlite
DB_OPERATORS_ALIASES=false
```
Exemplos de requisições para teste. Pode ser utilizado também outras ferramentas como [Postman](https://www.postman.com/). Utilizando o CURL, temos:
Para simular o torneio:
##### POST - /v1/tournaments/simulate
```bash=
curl -XPOST -H 'Content-type: application/json' 'http://localhost:5000/v1/tournaments/simulate'
```
##### Tipos de repostas possíveis
| Code HTTP | Descrição |
|:----------:|:-------------:|
| 200 | Simulação de torneio realizada com sucesso. |
| 500 | Erro interno no servidor. Contacte o administrador. |
##### Estrutura do corpo da resposta em caso de sucesso
```json=
{
"groups": [
{
"id": 1,
"name": "Group N",
"group_phase_id": 1,
"status": true,
"createdAt": "2020-07-16T00:32:51.000Z",
"updatedAt": "2020-07-16T00:32:51.000Z"
},
...
],
"rounds": [
{
"id": 1,
"name": "Round #ijwo",
"playoffs_phase_id": 1,
"status": true,
"createdAt": "2020-07-16T00:32:52.000Z",
"updatedAt": "2020-07-16T00:32:52.000Z"
},
...
]
"rankings": [
{
"group_id": 1,
"team_id": 1,
"winning_amount": 3,
"defeats_amount": 5,
"balance_rounds_in_favor": 15
},
...
],
"matches": [
{
"visiting_team_score": 16,
"host_team_score": 15,
"status": true,
"id": 1,
"source_id": 1,
"source_type": "group",
"visiting_team_id": 2,
"host_team_id": 1,
"updatedAt": "2020-07-16T02:09:50.655Z",
"createdAt": "2020-07-16T02:09:49.514Z"
},
...
],
"teams": [
{
"id": 1,
"name": "Flowerpecker Uppobje ",
"status": true,
"createdAt": "2020-07-16T00:32:52.000Z",
"updatedAt": "2020-07-16T00:32:52.000Z"
},
...
],
"champion": {
"id": 54,
"name": "Rhea Gordon ",
"status": true,
"createdAt": "2020-07-16T00:32:52.000Z",
"updatedAt": "2020-07-16T00:32:52.000Z"
}
}
```
##### Estrutura do corpo da resposta em caso de falha
```json=
"error": {
"message": "Server internal error. Contact the administrator."
}
```
Para consultar a situação do servidor (health checker):
##### GET - /health
```bash=
curl -XGET -H "Content-type: application/json" 'http://localhost:5000/health'
```
##### Tipos de repostas possíveis
| Code HTTP | Descrição |
|:----------:|:-------------:|
| 200 | Servidor operacional. |
| 5XX | Servidor inoperacional. |
##### Estrutura do corpo da resposta
```json=
```