Esse projeto contém uma série de informações sobre o que eu aprendi aqui na Trybe ao longo do curso de desenvolvimento web da Trybe.
O TFC
é um site informativo sobre partidas e classificações de futebol! ⚽️
No time de desenvolvimento do TFC
, seu squad ficou responsável por desenvolver uma API (utilizando o método TDD
) e também integrar - através do docker-compose - as aplicações para que elas funcionem consumindo um banco de dados.
Nesse projeto, pude construir um back-end dockerizado utilizando modelagem de dados através do Sequelize. O desenvolvimento respeita regras de negócio providas no projeto e sua API foi capaz de ser consumida por um front-end já provido nesse projeto.
Para adicionar uma partida é necessário ter um token, portanto a pessoa deverá estar logada para fazer as alterações. Teremos um relacionamento entre as tabelas teams
e matches
para fazer as atualizações das partidas.
O seu back-end implementou regras de negócio para popular adequadamente a tabela disponível no front-end que é exibida para a pessoa usuária do sistema.
Esse projeto foi proposto pelo curso de desenvolvimento web da Trybe.
Esse projeto foi desenvolvido no bloco de back-end e foi possível treinar a linguagem TypeScript, através do MySQL, sendo usados os princípios SOLID e POO.
Os commits foram feitos de acordo com os requisitos finalizados.
Todo o projeto foi feita na branch 'juliana-oliveira-project-tfc', isso por conta da exigência do curso.
Precisa utilizar o comando $npm install, a fim de instalar as dependências do projeto.
O teste acontece de cada desafio, através do comando $npm test.
- Será um container docker MySQL já configurado no docker-compose através de um serviço definido como
db
. - Tem o papel de fornecer dados para o serviço de backend.
- Durante a execução dos testes sempre vai ser acessado pelo
sequelize
e via porta3002
dolocalhost
; - Você também pode conectar a um Cliente MySQL (Workbench, Beekeeper, DBeaver e etc), colocando as credenciais configuradas no docker-compose no serviço
db
.
- Será o ambiente que você realizará a maior parte das implementações exigidas.
- Deve rodar na porta
3001
, pois o front-end faz requisições para ele nessa porta por padrão; - Sua aplicação deve ser inicializada a partir do arquivo
app/backend/src/server.ts
; - Garanta que o
express
é executado e a aplicação ouve a porta que vem das variáveis de ambiente; - Todas as dependências extras (tal como
joi
,boom
,express-async-errors
...) devem ser listadas emapp/backend/packages.npm
.
- O front já está concluído, não é necessário realizar modificações no mesmo. A única exceção será seu Dockerfile que precisará ser configurado.
- Todos os testes a partir do requisito de login usam o
puppeteer
para simular uma pessoa acessando o sitehttp://localhost:3000/
; - O front se comunica com serviço de back-end pela url
http://localhost:3001
através dos endpoints que você deve construir nos requisitos. - Recomendamos que sempre que implementar um requisito no back-end acesse a página no front-end que consome a implementação para validar se está funcionando como esperado.
- O
docker-compose
tem a responsabilidade de unir todos os serviços conteinerizados (backend, frontend e db) e subir o projeto completo com o comandonpm run compose:up
ounpm run compose:up:dev
; - Você deve configurar as
Dockerfiles
corretamente nas raízes dofront-end
eback-end
, para conseguir inicializar a aplicação;
- Sistema Operacional Distribuição Unix
- Node versão 16
- Docker
- Docker-compose versão >=1.29.2
No diretório app/backend/
, contém o arquivo .env
. Nele, você precisa alterar os valores de acordo com o cenário do seu ambiente (credenciais de banco de dados, secrets desejadas e etc). Isso vai permitir que você inicialize a aplicação fora do container e ela se conecte com seu banco local caso deseje.
TRYBE_FUTEBOL_CLUBE
.
Esse foi um projeto individual,que desenvolvido somente por Juliana Oliveira.
Foi usado Visual Studio Code, além do Trello que auxiliou na organização das tarefas.
Nenhum.
No trabalho do desenvolvimento de software a gente sempre tem prazos, muitas vezes os prazos são apertados.
Por outro lado, eu não quero criar algo que não entendo perfeitamente, como também fazer códigos rápidos pode levar a erros que podem demorar muito pra corrigir.
Por isso, usei e sempre uso o método Baby Steps, que é uma estratégia de abordar o desafio passo à passo, defensivamente.
Baby steps é um termo em inglês que quer dizer passos de bebê. Refere-se a fazer as coisas, quaisquer que sejam, devagar, com calma, passo a passo.
Esse projeto é composto de 4 seções principais:
- Users e Login
- Times
- Partidas
- Placar
- Comece rodando o comando
npm run build
na pasta doback-end
para fazer o build da aplicação; - Nessa seção temos o diagrama de entidades;
- Mantenha o arquivo
/app/backend/src/database/migrations/99999999999999-create-z.js
, pois ele é necessário para a avaliação dos requisitos dessa seção; - A leitura da seção
Bônus: Model com Sequelize
no conteúdo deTypeScript: Tipagem Estática e Generics
, contido nesse link, é recomendável!
Introdução
-
A rota utilizada deve ser (
/login
); -
A rota deve receber os campos
email
epassword
e esses campos devem ser validados no banco de dados:- O campo
email
deve receber um email válido; - O Campo
password
deve ter mais de 6 caracteres.
- O campo
-
O body da requisição deve conter o seguinte formato:
{ "email": "string", "password": "string" }
Requisitos
👣Requisito 1 - Desenvolva em /app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela users
- O avaliador consultará os dados da tabela
users
, verificando se ela contém os dados iniciais corretos. Nessa seção temos o diagrama de entidades;
👣Requisito 2 - (TDD
) Desenvolva testes que cubram no mínimo 5% dos arquivos back-end em /src
, com um mínimo de 7 linhas cobertas
Sugestões:
- Baseando-se no contrato do endpoint
/login
do próximo requisito, inicie um teste de integração utilizando a metodologiaTDD
com a implementação do requisito seguinte; - Nesse primeiro momento, foque em desenvolver o que pede o requisito, progredindo gradualmente a partir disso;
- Para tanto, utilize/altere o arquivo de referência
app/backend
/src/tests/change.me.test.ts
; - Veja a seção de Testes de cobertura para mais detalhes.
👣Requisito 3 - Desenvolva o endpoint /login
no back-end de maneira que ele permita o acesso com dados válidos no front-end
-
A rota de ser do tipo
POST
; -
O avaliador verificará se é possível fazer o login com dados corretos e que, após o acesso, será redirecionado para a tela de jogos.
-
As senhas que existem no banco de dados estão encriptadas. Veja a seção de Criptografia de Senhas para mais detalhes de como comparar a senha do banco com a senha do corpo da requisição.
-
Se o login foi feito com sucesso, o resultado retornado deverá ser similar ao exibido abaixo, com um status http
200
:{ "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjU0NTI3MTg5fQ.XS_9AA82iNoiVaASi0NtJpqOQ_gHSHhxrpIdigiT-fc" // Aqui deve ser o token gerado pelo backend. }
👣Requisito 4 - (TDD
) Desenvolva testes que cubram no mínimo 10% dos arquivos back-end em /src
, com um mínimo de 19 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando o contrato do próximo requisito.
👣Requisito 5 - Desenvolva o endpoint /login
no back-end de maneira que ele não permita o acesso sem informar um email no front-end
-
O avaliador verificará se fazer o login sem um email, haverá o retorno de status bad request.
-
Se o login não tiver o campo "email", o resultado retornado deverá ser a mensagem abaixo, com um status http
400
:
{ "message": "All fields must be filled" }
👣Requisito 6 - (TDD
) Desenvolva testes que cubram no mínimo 15% dos arquivos back-end em /src
, com um mínimo de 25 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando o contrato do próximo requisito.
👣Requisito 7 - Desenvolva o endpoint /login
no back-end de maneira que ele não permita o acesso sem informar uma senha no front-end
-
O avaliador verificará se fazer login sem senha, o retorno será status bad request.
-
Se o login não tiver o campo "password", o resultado retornado deverá ser conforme exibido abaixo, com um status http
400
:
{ "message": "All fields must be filled" }
👣Requisito 8 - (TDD
) Desenvolva testes que cubram no mínimo 20% dos arquivos back-end em /src
, com um mínimo de 35 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando o contrato do próximo requisito.
👣Requisito 9 - Desenvolva o endpoint /login
no back-end de maneira que ele não permita o acesso com um email inválido no front-end
-
O avaliador verificará se fazer o login com um email incorreto retornará status não-autorizado.
-
Se o login tiver o "email" inválido, o resultado retornado será similar ao exibido abaixo, com um status http
401
:
{ "message": "Incorrect email or password" }
👣Requisito 10 - (TDD
) Desenvolva testes que cubram no mínimo 30% dos arquivos back-end em /src
, com um mínimo de 45 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/login
, utilizando o métodoTDD
, agora considerando os contratos dos próximos dois requisitos.
👣Requisito 11 - Desenvolva o endpoint /login
no back-end de maneira que ele não permita o acesso com uma senha inválida no front-end
-
O avaliador verificará se fazer o login com uma senha incorreta retornará status não-autorizado.
-
Se o login tiver a "senha" inválida, o resultado retornado deverá ser conforme exibido abaixo, com um status http
401
:
{ "message": "Incorrect email or password" }
👣Requisito 12 - Desenvolva o endpoint /login/validate
no back-end de maneira que ele retorne os dados corretamente no front-end
-
Deve ser uma rota
GET
que receba umheader
com parâmetroauthorization
, onde ficará armazenado o token gerado no login; -
O avaliador verificará se ao tentar bater na rota com um token válido, o mesmo retornará o tipo de usuário.
A resposta deve ser de status 200
com um objeto
contendo a role
do user:
{ "role": "admin" }
Introdução
- Os requisitos a seguir consideram o consumo da rota
/teams
para retornar os nomes dos times associados à partida na renderização do front-end
Requisitos
👣Requisito 13 - (TDD
) Desenvolva testes que cubram no mínimo 45% dos arquivos back-end em /src
, com um mínimo de 70 linhas cobertas
Sugestão:
- Crie um novo teste de integração, agora da sua rota
/teams
, utilizando o métodoTDD
, considerando os contratos dos próximos dois requisitos. Nessa seção temos o diagrama de entidades.
👣Requisito 14 - Desenvolva em /app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela de teams
- O avaliador consultará os dados da tabela
teams
, verificando se ela contém os dados iniciais corretos. Nessa seção temos o diagrama de entidades.
👣Requisito 15 - Desenvolva o endpoint /teams
no back-end de forma que ele possa retornar todos os times corretamente
- Deve ser uma rota
GET
com resposta com status200
e com umjson
contendo o retorno no seguinte modelo:
[
{
"id": 1,
"teamName": "Avaí/Kindermann"
},
{
"id": 2,
"teamName": "Bahia"
},
{
"id": 3,
"teamName": "Botafogo"
},
...
]
👣Requisito 16 - Desenvolva o endpoint /teams/:id
no back-end de forma que ele possa retornar dados de um time específico
- Deve ser uma rota
GET
com resposta com status200
e com umjson
contendo o retorno no seguinte modelo:
{
"id": 5,
"teamName": "Cruzeiro"
}
👣Requisito 17 - (TDD
) Desenvolva testes que cubram no mínimo 60% dos arquivos back-end em /src
, com um mínimo de 80 linhas cobertas
Sugestão:
- Crie um novo teste de integração, agora da sua rota
/matches
, utilizando o métodoTDD
, agora considerando os contratos dos próximos três requisitos.
Introdução
- Para os requisitos de criação de partidas, será necessário implementar o model e algumas rotas relacionadas a entidade Match.
Requisitos
👣Requisito 18 - Desenvolva em /app/backend/src/database
nas pastas correspondentes, uma migration e um model para a tabela de matches
- O avaliador consultará os dados da tabela
matches
, verificando se ela contém os dados iniciais corretos. Nessa seção temos o diagrama de entidades.
👣Requisito 19 - Desenvolva o endpoint /matches
de forma que os dados apareçam corretamente na tela de partidas no front-end.
-
A rota deve ser um
GET
e retorna uma lista de partidas; -
Será validado que a página apresentará todos os dados de partidas sem nenhum filtro.
Exemplo de retorno:
[ { "id": 1, "homeTeam": 16, "homeTeamGoals": 1, "awayTeam": 8, "awayTeamGoals": 1, "inProgress": false, "teamHome": { "teamName": "São Paulo" }, "teamAway": { "teamName": "Grêmio" } }, ... { "id": 41, "homeTeam": 16, "homeTeamGoals": 2, "awayTeam": 9, "awayTeamGoals": 0, "inProgress": true, "teamHome": { "teamName": "São Paulo" }, "teamAway": { "teamName": "Internacional" } } ]
-
OBS: Você deverá definir os relacionamentos para
teamHome
eteamAway
somente na model de partidas.
👣Requisito 20 - Desenvolva o endpoint /matches
de forma que seja possível filtrar as partidas em andamento na tela de partidas do front-end
-
A rota deverá ser do tipo
GET
e retornar uma lista de partidas filtradas; -
Será validado que, ao escolher a opção de partidas em andamento, serão filtradas todas as partidas em andamento;
-
Essa requisição deverá usar
query string
para definir o parâmetro: ex:matches?inProgress=true
Exemplo de retorno da requisição:
[
{
"id": 41,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 9,
"awayTeamGoals": 0,
"inProgress": true,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Internacional"
}
},
{
"id": 42,
"homeTeam": 6,
"homeTeamGoals": 1,
"awayTeam": 1,
"awayTeamGoals": 0,
"inProgress": true,
"teamHome": {
"teamName": "Ferroviária"
},
"teamAway": {
"teamName": "Avaí/Kindermann"
}
}
]
👣Requisito 21 - Desenvolva o endpoint /matches
de forma que seja possível filtrar as partidas finalizadas na tela de partidas do front-end
-
A rota deverá ser do tipo
GET
e retornar uma lista de partidas filtradas; -
Será validado que,ao escolher a opção de partidas finalizadas, serão filtradas todas as partidas finalizadas;
-
Essa requisição deverá usar
query string
para definir o parâmetro. ex:matches?inProgress=false
Exemplo de retorno da requisição:
[
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 1,
"awayTeam": 8,
"awayTeamGoals": 1,
"inProgress": false,
"teamHome": {
"teamName": "São Paulo"
},
"teamAway": {
"teamName": "Grêmio"
}
},
{
"id": 2,
"homeTeam": 9,
"homeTeamGoals": 1,
"awayTeam": 14,
"awayTeamGoals": 1,
"inProgress": false,
"teamHome": {
"teamName": "Internacional"
},
"teamAway": {
"teamName": "Santos"
}
}
]
👣Requisito 22 - (Bônus
; TDD
) Desenvolva testes que cubram no mínimo 80% dos arquivos back-end em /src
, com um mínimo de 100 linhas cobertas
Sugestão:
- Evolua os testes de integração da sua rota
/matches
, utilizando o métodoTDD
, agora considerando o contrato dos próximos requisitos.
👣Requisito 23 - Desenvolva o endpoint /matches
de modo que seja possível salvar uma partida com o status de inProgress como true no banco de dados
-
A rota deverá ser do tipo
POST
e retornar a partida inserida no banco de dados; -
Será validado que é possível salvar um jogo no banco de dados e ver o jogo na página de jogos;
-
A partida só pode ser criada com token JWT validado;
-
O corpo da requisição terá o seguinte formato:
{
"homeTeam": 16, // O valor deve ser o id do time
"awayTeam": 8, // O valor deve ser o id do time
"homeTeamGoals": 2,
"awayTeamGoals": 2
}
- Caso a partida seja inserida com sucesso, deve-se retornar os dados da partida, com status
201
:
{
"id": 1,
"homeTeam": 16,
"homeTeamGoals": 2,
"awayTeam": 8,
"awayTeamGoals": 2,
"inProgress": true,
}
👣Requisito 24 - Desenvolva o endpoint /matches/:id/finish
de modo que seja possível alterar o status inProgress de uma partida para false no banco de dados
-
A rota deve ser do tipo
PATCH
; -
Será recebido o
id
pelo parâmetro da URL; -
Será validado que, ao finalizar uma partida, a alteração é feita no banco de dados e na página.
-
Deve-se retornar, com um status
200
, a seguinte mensagem:
{ "message": "Finished" }
👣Requisito 25 - Desenvolva o endpoint /matches
de forma que não seja possível inserir uma partida com times iguais
-
Será validado que não é possível inserir uma partida com times iguais;
-
Não deve ser possível criar uma partida com o mesmo time, por exemplo: Barcelona x Barcelona. Caso isso ocorra, deve-se retornar, com um status
401
, a seguinte mensagem::
{ "message": "It is not possible to create a match with two equal teams" }
👣Requisito 26 - Desenvolva o endpoint /matches
de forma que não seja possível inserir uma partida com um time que não existe na tabela teams
-
Será validado que não é possível inserir uma partida com um time que não existe na tabela teams;
-
Caso algum dos times não esteja cadastrado no banco de dados, deve-se retornar, com um status
404,
a seguinte mensagem:
{ "message": "There is no team with such id!" }
👣Requisito 27 - Desenvolva o endpoint /matches
de forma que não seja possível inserir uma partida sem um token válido
-
Será validado que não é possível inserir uma partida com um token inválido;
-
Caso o token informado não seja válido, deve-se retornar, com um status
401
, a seguinte mensagem:
{ "message": "Token must be a valid token" }
👣Requisito 28 - Desenvolva o endpoint /matches/:id
de forma que seja possível atualizar partidas em andamento
-
O endpoint deve ser do tipo
PATCH
; -
Será recebido o
id
pelo parâmetro da URL; -
Será avaliado que é possível alterar o resultado de uma partida.
-
O corpo da requisição terá o seguinte formato:
{
"homeTeamGoals": 3,
"awayTeamGoals": 1
}
- Será avaliado que é o endpoint responde à requisição com um status
200
e qualquer corpo.
Introdução
- `Classificação`: Posição na classificação;
- `Time`: Nome do time;
- `P`: Total de Pontos;
- `J`: Total de Jogos;
- `V`: Total de Vitórias;
- `E`: Total de Empates;
- `D`: Total de Derrotas;
- `GP`: Gols marcados a favor;
- `GC`: Gols sofridos;
- `SG`: Saldo total de gols;
- `%`: Aproveitamento do time.
<br/>
-
Todas as regras de negócio e cálculos necessários deverão ser realizados no seu back-end. A aplicação front-end apenas renderizará essas informações.
-
Para calcular o
Total de Pontos
, você deve levar em consideração que:- O time
vitorioso
: marcará +3 pontos; - O time
perdedor
: marcará 0 pontos; - Em caso de
empate
: ambos os times marcam +1 ponto.
- O time
-
Para o campo
Aproveitamento do time (%)
, que é a porcentagem de jogos ganhos, use a seguinte fórmula:P/(J*3)*100
, onde:P
: Total de Pontos;J
: Total de Jogos.
Obs.: O seu resultado deverá ser limitado a
duas casas decimais
. -
Para calcular
Saldo de Gols
use a seguinte fórmula:GP - GC
, onde:GP
: Gols marcados a favor;GC
: Gols sofridos.
-
O resultado deverá ser ordenado sempre de forma decrescente, levando em consideração a quantidade de pontos que o time acumulou. Em caso de empate no
Total de Pontos
, você deve levar em consideração os seguintes critérios para desempate:
Ordem para desempate
1º Total de Vitórias; 2º Saldo de gols; 3º Gols a favor; 4º Gols sofridos.
- Por padrão, as respostas de todos os seus endpoints deverão estar em inglês, mesmo que a renderização no front-end seja em português.
- A sua tabela deverá renderizar somente as PARTIDAS que já foram FINALIZADAS! Os seguintes pontos serão avaliados:
- Se a lista de classificação está correta;
- Se a regra de classificação se mantém mesmo com mudanças na classificação;
- Se a tabela de classificação tem 10 colunas;
- Se a tabela tem uma linha para cada time.
Exemplo de retorno esperado:
[
{
"name": "Palmeiras",
"totalPoints": 13,
"totalGames": 5,
"totalVictories": 4,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 17,
"goalsOwn": 5,
"goalsBalance": 12,
"efficiency": 86.67
},
{
"name": "Corinthians",
"totalPoints": 12,
"totalGames": 5,
"totalVictories": 4,
"totalDraws": 0,
"totalLosses": 1,
"goalsFavor": 12,
"goalsOwn": 3,
"goalsBalance": 9,
"efficiency": 80
},
{
"name": "Santos",
"totalPoints": 11,
"totalGames": 5,
"totalVictories": 3,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 12,
"goalsOwn": 6,
"goalsBalance": 6,
"efficiency": 73.33
},
...
]
-
Os endpoints dessa seção, irão alimentar uma tabela idêntica ao exemplo abaixo no front-end:
Classificação Time P J V E D GP GC SG % 1 Ferroviária 38 15 12 2 1 44 13 31 84.4
Requisitos
👣Requisito 29 - Desenvolva o endpoint /leaderboard/home
de forma que seja possível filtrar as classificações dos times da casa
na tela de classificação do front-end com os dados iniciais do banco de dados
-
O endpoint deverá ser do tipo
GET
; -
Será avaliado que ao fazer a requisição ao endpoint
/leaderboard/home
serão retornados os campos e valores corretos, considerando os dados iniciais do banco de dados; -
Partidas que estiverem em andamento (não foram finalizadas) não devem ser consideradas.
Retorno esperado:
[
{
"name": "Santos",
"totalPoints": 9,
"totalGames": 3,
"totalVictories": 3,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 9,
"goalsOwn": 3,
"goalsBalance": 6,
"efficiency": "100.00"
},
{
"name": "Palmeiras",
"totalPoints": 7,
"totalGames": 3,
"totalVictories": 2,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 10,
"goalsOwn": 5,
"goalsBalance": 5,
"efficiency": "77.78"
},
{
"name": "Corinthians",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 6,
"goalsOwn": 1,
"goalsBalance": 5,
"efficiency": "100.00"
},
{
"name": "Grêmio",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 4,
"goalsOwn": 1,
"goalsBalance": 3,
"efficiency": "100.00"
},
{
"name": "Real Brasília",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 2,
"goalsOwn": 0,
"goalsBalance": 2,
"efficiency": "100.00"
},
{
"name": "São Paulo",
"totalPoints": 4,
"totalGames": 2,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 4,
"goalsOwn": 1,
"goalsBalance": 3,
"efficiency": "66.67"
},
{
"name": "Internacional",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 4,
"goalsOwn": 6,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Botafogo",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 2,
"goalsOwn": 4,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Ferroviária",
"totalPoints": 3,
"totalGames": 2,
"totalVictories": 1,
"totalDraws": 0,
"totalLosses": 1,
"goalsFavor": 3,
"goalsOwn": 2,
"goalsBalance": 1,
"efficiency": "50.00"
},
{
"name": "Napoli-SC",
"totalPoints": 2,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 2,
"goalsOwn": 2,
"goalsBalance": 0,
"efficiency": "33.33"
},
{
"name": "Cruzeiro",
"totalPoints": 1,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 2,
"goalsOwn": 3,
"goalsBalance": -1,
"efficiency": "16.67"
},
{
"name": "Flamengo",
"totalPoints": 1,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 1,
"goalsOwn": 2,
"goalsBalance": -1,
"efficiency": "16.67"
},
{
"name": "Minas Brasília",
"totalPoints": 1,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 2,
"goalsFavor": 3,
"goalsOwn": 6,
"goalsBalance": -3,
"efficiency": "11.11"
},
{
"name": "Avaí/Kindermann",
"totalPoints": 1,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 2,
"goalsFavor": 3,
"goalsOwn": 7,
"goalsBalance": -4,
"efficiency": "11.11"
},
{
"name": "São José-SP",
"totalPoints": 0,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 2,
"goalsOwn": 5,
"goalsBalance": -3,
"efficiency": "0.00"
},
{
"name": "Bahia",
"totalPoints": 0,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 0,
"goalsOwn": 4,
"goalsBalance": -4,
"efficiency": "0.00"
}
]
👣Requisito 30 - Desenvolva o endpoint /leaderboard/home
de forma que seja possível filtrar as classificações dos times da casa na tela de classificação do front-end, e atualizar a tabela ao inserir a partida Corinthians 2 X 1 Internacional
- Será avaliado que após acrescentar a partida Corinthians 2 X 1 Internacional e fazer a requisição ao endpoint
/leaderboard/home
, serão retornados os campos e valores corretos.
Retorno esperado:
[
{
"name": "Santos",
"totalPoints": 9,
"totalGames": 3,
"totalVictories": 3,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 9,
"goalsOwn": 3,
"goalsBalance": 6,
"efficiency": "100.00"
},
{
"name": "Corinthians",
"totalPoints": 9,
"totalGames": 3,
"totalVictories": 3,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 8,
"goalsOwn": 2,
"goalsBalance": 6,
"efficiency": "100.00"
},
{
"name": "Palmeiras",
"totalPoints": 7,
"totalGames": 3,
"totalVictories": 2,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 10,
"goalsOwn": 5,
"goalsBalance": 5,
"efficiency": "77.78"
},
{
"name": "Grêmio",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 4,
"goalsOwn": 1,
"goalsBalance": 3,
"efficiency": "100.00"
},
{
"name": "Real Brasília",
"totalPoints": 6,
"totalGames": 2,
"totalVictories": 2,
"totalDraws": 0,
"totalLosses": 0,
"goalsFavor": 2,
"goalsOwn": 0,
"goalsBalance": 2,
"efficiency": "100.00"
},
{
"name": "São Paulo",
"totalPoints": 4,
"totalGames": 2,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 0,
"goalsFavor": 4,
"goalsOwn": 1,
"goalsBalance": 3,
"efficiency": "66.67"
},
{
"name": "Internacional",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 4,
"goalsOwn": 6,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Botafogo",
"totalPoints": 4,
"totalGames": 3,
"totalVictories": 1,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 2,
"goalsOwn": 4,
"goalsBalance": -2,
"efficiency": "44.44"
},
{
"name": "Ferroviária",
"totalPoints": 3,
"totalGames": 2,
"totalVictories": 1,
"totalDraws": 0,
"totalLosses": 1,
"goalsFavor": 3,
"goalsOwn": 2,
"goalsBalance": 1,
"efficiency": "50.00"
},
{
"name": "Napoli-SC",
"totalPoints": 2,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 2,
"totalLosses": 0,
"goalsFavor": 2,
"goalsOwn": 2,
"goalsBalance": 0,
"efficiency": "33.33"
},
{
"name": "Cruzeiro",
"totalPoints": 1,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 2,
"goalsOwn": 3,
"goalsBalance": -1,
"efficiency": "16.67"
},
{
"name": "Flamengo",
"totalPoints": 1,
"totalGames": 2,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 1,
"goalsFavor": 1,
"goalsOwn": 2,
"goalsBalance": -1,
"efficiency": "16.67"
},
{
"name": "Minas Brasília",
"totalPoints": 1,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 2,
"goalsFavor": 3,
"goalsOwn": 6,
"goalsBalance": -3,
"efficiency": "11.11"
},
{
"name": "Avaí/Kindermann",
"totalPoints": 1,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 1,
"totalLosses": 2,
"goalsFavor": 3,
"goalsOwn": 7,
"goalsBalance": -4,
"efficiency": "11.11"
},
{
"name": "São José-SP",
"totalPoints": 0,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 2,
"goalsOwn": 5,
"goalsBalance": -3,
"efficiency": "0.00"
},
{
"name": "Bahia",
"totalPoints": 0,
"totalGames": 3,
"totalVictories": 0,
"totalDraws": 0,
"totalLosses": 3,
"goalsFavor": 0,
"goalsOwn": 4,
"goalsBalance": -4,
"efficiency": "0.00"
}
]