Existem dois torneios populares no futebol: a Liga dos Campeões e a Liga Europa. Com base nos resultados,
é calculado o chamado
Rating of Football Associates . Com base nessa classificação, é ainda determinado quantas equipes de cada país participarão dos torneios subsequentes.
Neste artigo, vou criar um aplicativo baseado na plataforma
lsFusion aberta e gratuita que calculará essa classificação. Ele armazenará todos os seus dados no PostgreSQL, fornecerá uma interface da web para alterá-los e exibi-los com recursos de filtragem e classificação, além de importar resultados de correspondências usando uma API especial.
Todo o código para implementar este aplicativo consistirá em cerca de 300 linhas significativas.
Lógica do domínio
A criação de qualquer sistema de informação começa com a tarefa da lógica do domínio.
Antes de tudo, é lógico destacar os diretórios mais simples que possuem apenas um código e um nome:
- Torneio Liga dos Campeões ou Liga Europa.
- Temporada . 2018-2019 / 2017-2018 etc.
- Rodada . Final, Semifinal, Fase de Grupos, etc. Pode ser considerado uma composição para o torneio, mas nesta implementação eu o destaquei como uma entidade separada.
- País de origem Esta aplicação é usada como a Associação de Futebol. Por exemplo, o clube de Mônaco está localizado no país de Mônaco, mas joga no campeonato francês.
- Club Barcelona, Real Madrid, Manchester United, etc.
Como o lsFusion usa o mesmo tipo de lógica para declará-los, declararemos um metacódigo (ou modelo de código) que gerará a lógica correspondente:
Metacódigo da Declaração de Diretório Ele anunciará:
- Classe com nome próprio
- Propriedades com código e nome para a nova classe
- Três formulários: edição de um objeto, um formulário com uma lista de todos os objetos, que são adicionados ao navegador, uma caixa de diálogo para selecionar esse objeto. Como um diálogo, você pode usar o segundo formulário, mas o usuário terá a oportunidade de alterar os objetos ao escolher, o que pode levar a erros por parte dos usuários.
Quatro parâmetros são passados para o metacódigo:
- Identificador (objeto) . Com esse nome, classes e formulários serão criados. A construção ### é usada para colocar a primeira letra do identificador em maiúscula no código resultante.
- Nome no singular . Usado para o título da classe e do formulário.
- O nome está no plural . Usado para caixa de combinação e caixa de diálogo.
- Nome Comprimento . Nos nomes de objetos diferentes, são esperados comprimentos diferentes, o que é importante ao criar a interface.
Usando o metacódigo criado, adicione as cinco entidades descritas acima:
O código gerado, por exemplo, para um torneio terá a seguinte aparência:
Adicione o link ao país à lógica do clube gerada. Para fazer isso, primeiro crie a propriedade correspondente, que depois será colocada nas formas de edição e exibição do clube:
Colocamos toda a lógica criada em um módulo Master separado (arquivo Master.lsf).
Agora crie uma entidade
League . Ela determinará o torneio de uma temporada específica. Por exemplo, Liga dos Campeões 2017-18 ou Liga Europa 2018-19. A liga não terá nome, mas apenas links para o torneio e a temporada. Portanto, não usaremos o metacódigo anterior, mas faremos a mesma lógica e a colocaremos no novo módulo League:
E, finalmente, adicione a lógica das correspondências. Para fazer isso, crie a classe
Match , que se refere à liga e à rodada. Para ele, os clubes que participaram e o resultado também serão solicitados. Colocamos tudo isso em um módulo Match separado:
Importação de dados
Infelizmente, consegui encontrar apenas uma API pública e gratuita que suporta todos os Eurocups. Esta é
a API do futebol . No entanto, existem problemas:
- Não há resultados até 2016.
- Não há qualificações para a Liga Europa até 2018.
- Existem certos erros nos dados. Por exemplo, Irtysh Pavlodar está designado para a Rússia, embora este clube represente o Cazaquistão. Além disso, Europa Fc, por algum motivo, refere-se à Espanha, em vez de Gibraltar.
Os erros de dados podem ser corrigidos manualmente usando formulários criados anteriormente. No entanto, como o cálculo do coeficiente total é baseado nos últimos cinco anos, infelizmente, não funcionará para calcular o coeficiente total a partir dos dados da API Football. Se alguém nos comentários sugerir onde obter os dados necessários em qualquer formato dos anos anteriores, ficarei muito agradecido. Porém, como há dados completos para 2018, será possível verificar a correção do cálculo pelo menos para este ano.
A API de que precisamos é implementada na forma de solicitações HTTP, onde os parâmetros são transmitidos via url e uma chave de acesso especial é indicada no cabeçalho. Declare a lógica correspondente:
Todas as ações de importação de dados serão colocadas no formulário de
ligas criadas anteriormente. Lá colocaremos a chave de acesso na barra de ferramentas da tabela com a lista de ligas:
Primeiro, implementamos a lista de ligas. Para isso, a API do Football possui um URL especial: / ligas. Uma solicitação GET para ele retorna JSON do formulário:
A resposta { "api":{ "results":2, "leagues":[ { "league_id":1, "name":"2018 Russia World Cup", "country":"World", "country_code":null, "season":2018, "season_start":"2018-06-14", "season_end":"2018-07-15", "logo":"https://www.api-football.com/public/leagues/1.png", "flag":null, "standings":0, "is_current":1 }, { "league_id":2, "name":"Premier League", "country":"England", "country_code":"GB", "season":2018, "season_start":"2018-08-10", "season_end":"2019-05-12", "logo":"https://www.api-football.com/public/leagues/2.png", "flag":"https://www.api-football.com/public/flags/gb.svg", "standings":1, "is_current":1 } ] } }
Para gerar uma solicitação GET e registrar o corpo da resposta, a seguinte construção é usada:
Ele grava o resultado na propriedade local
result sem parâmetros do tipo FILE.
Para analisar um arquivo no formato JSON, é criado um formulário cuja estrutura corresponde à estrutura JSON. Você pode gerá-lo no IDE usando o item de menu:

Para o JSON acima, o formulário será semelhante a este (levando em consideração apenas os valores que serão importados):
Para importar diretamente da propriedade de
resultado JSON no formato do formulário
importLeagues, use o seguinte comando:
Após sua execução, os valores correspondentes do arquivo JSON serão colocados nas propriedades
tournamentName ,
seasonName e
leagueId :

Ou seja, o valor do nome do
torneio (0) será "Copa do Mundo" e, no nome do
torneio (1), será "Premier League".
Infelizmente, o API Football não possui uma entidade de torneio. A única maneira de vincular todas as ligas é ter um nome que corresponda às ligas do mesmo torneio de diferentes épocas do ano. Para isso, na importação, primeiro agrupamos todos os nomes das ligas importadas e, se não estiver no banco de dados, criamos novos torneios:
Também não há códigos para as estações do ano, portanto, ao importar ligas, elas são criadas da mesma maneira. Após a criação dos objetos ausentes, as ligas são importadas diretamente. Os torneios e as temporadas são pesquisados por nome usando as propriedades criadas anteriormente pelo
GROUP AGGR :
Por padrão, os dados serão carregados, mas serão salvos no banco de dados somente quando o usuário clicar no botão Salvar no formulário. Se necessário, você pode adicionar o comando
APPLY no final da ação para que ele seja salvo imediatamente no banco de dados sem uma visualização.
E, finalmente, adicione a ação de importação ao formulário da lista de ligas:
Da mesma forma, importamos clubes e partidas. No entanto, como a API fornece a capacidade de importá-los apenas para uma liga específica, a ação deve levar a liga como uma entrada:
Importar clubes e partidasHá uma peculiaridade para as partidas: os códigos dos times são
incluídos nas tags homeTeam e
awayTeam adicionais . Grupos correspondentes são criados para eles por analogia com api. Além disso, eles têm as mesmas tags
team_id . Como as propriedades com o mesmo nome não podem ser incluídas no formulário, é
usada a palavra-chave
EXTID especial, que define o nome da marca no JSON importado.
Para que todas as importações estejam na mesma forma e, como estão vinculadas às ligas, as levamos para a mesma forma. Além disso, adicionamos equipes e correspondências ao formulário para poder ver o que é importado antes de salvar:
O formulário resultante terá a seguinte aparência:

Todas as importações serão colocadas em um módulo APIFootball separado.
Cálculo do coeficiente
Prosseguimos diretamente no cálculo do coeficiente de país da UEFA. É lógico colocar todo o código em um módulo da UEFA especialmente instalado para isso.
Primeiro, lembre-se de que a API Football fornece uma interface para importar todas as partidas, e não apenas as Eurocups. Portanto, separamos as partidas da Eurocup de acordo com o nome do torneio (é mais correto ter uma propriedade primária separada para isso, mas a implementação das propriedades sempre pode ser alterada sem modificar o restante da lógica):
Primeiro, vamos calcular os pontos que cada clube recebe em uma temporada pelos resultados de partidas específicas.
Durante esse período, cada equipe recebe:
2 pontos em caso de vitória;
1 ponto em caso de empate.
Desde 1999, esses pontos são divididos em dois se forem conquistados em rodadas de qualificação, ou seja:
1 ponto em caso de vitória;
0,5 pontos por empate.
Crie propriedades auxiliares que determinam a relação entre a partida e o clube:
Para determinar quantos pontos são marcados em cada partida, adicionamos a propriedade principal do tipo numérico da rodada, que por padrão será igual a um:
Depois, contamos pontos para vitórias e empates e somamos:
Os pontos para as partidas são marcados como MATERIALIZED, para que sejam salvos na tabela e não sejam calculados sempre.
Agora você precisa contar pontos de bônus:
Além disso, pontos de bônus são concedidos:
1 ponto é dado caso a equipe chegue às quartas de final, semifinais e finais nas Copas da Europa;
4 pontos por alcançar a fase de grupos da Liga dos Campeões (até 1996 - 2 pontos, de 1997 a 2003 - 1 ponto, de 2004 a 2008 - 3 pontos);
5 pontos no caso de uma equipe sair para a 1/8 de final da Liga dos Campeões (antes de 2008 - 1 ponto).
Apenas partidas jogadas são levadas em consideração (perdas técnicas não são levadas em consideração). As partidas que terminam em uma série de pênaltis, no cálculo do coeficiente, são consideradas de acordo com o resultado, que é fixado pelos resultados do jogo no horário principal e no prolongamento.
Nesta implementação, assumimos que o clube entrou na rodada do torneio se ele jogou pelo menos uma partida. Para isso, calculamos quantas partidas o clube disputou em uma temporada, torneio ou rodada específica:
Agora você precisa determinar quantos pontos serão marcados para a passagem em uma rodada específica. Uma vez que depende do torneio (por exemplo, uma passagem na Liga dos Campeões recebe 5 pontos, mas nada na Liga Europa). Para fazer isso, apresentamos a propriedade principal:
Agora vamos calcular pontos de bônus e o número total de pontos do clube para a temporada:
Por fim, vamos diretamente ao coeficiente do país.
Para calcular a classificação da associação, todos os pontos marcados pelos clubes participantes da Liga dos Campeões e da Liga Europa são somados, e o resultado é dividido pelo número de clubes dessa associação [2] [3].
Vamos calcular o número de clubes de cada associação que participou de competições europeias:
Agora, consideramos o número total de pontos de associação para a temporada e dividimos pelo número de clubes:
A classificação de um país é a soma dos coeficientes do país nos últimos 5 anos.
Para fazer isso, numeramos todas as estações começando do último pelo código interno (assumimos que o último foi adicionado posteriormente e possui um código maior):
Se necessário, você pode inserir um campo ou número separado por nome.
Resta apenas calcular a classificação final para o país:
Acima, anunciamos chances de torneios e rodadas. Adicione-os ao formulário de edição de torneios, enquanto filtra apenas as rodadas que ocorreram nesses torneios:
Configurações de probabilidades, por exemplo, para a Liga dos Campeões que você precisa definir assim:

Vamos desenhar um formulário que exibirá a classificação, onde as equipes serão mostradas para cada país e para cada equipe suas partidas:
O formulário resultante terá a seguinte aparência:

A cor nas tabelas dos clubes mostra quando ele participou das temporadas e da tabela de jogos - quem venceu.
A imagem mostra que as classificações para 2018 são calculadas exatamente da mesma forma que na Wikipedia. Nos anos anteriores, como mencionado acima, o Football API não fornece todas as informações.
Sumário
Criamos um pequeno aplicativo que é totalmente descrito pelo código acima e armazena seus dados no PostgreSQL, fornece uma interface da web para visualizar e editar dados. Ao mesmo tempo, funcionará efetivamente em grandes volumes, pois todos os formulários lêem apenas a janela visível. Também estão disponíveis filtros, classificação, carregamento para o Excel e muito mais.
Deve-se notar a facilidade com que, usando a plataforma, a tarefa de calcular o coeficiente foi decomposta em propriedades individuais. Quando executada, toda essa lógica será convertida em consultas SQL e todos os cálculos serão executados diretamente no servidor de banco de dados usando todas as otimizações do DBMS.
Um exemplo de como o aplicativo funciona com os dados carregados nele pode ser encontrado em:
https://demo.lsfusion.org/euroleague . Login de convidado sem senha. O usuário está no modo somente leitura.
Quem desejar pode
definir tudo localmente e, por exemplo, modelar os coeficientes inserindo os resultados de futuras correspondências. Todos os módulos de aplicativos descritos acima estão hospedados no
github . Após a instalação automática, você só precisa exibir esses arquivos na pasta apropriada nas instruções e reiniciar o servidor.
Para fazer o download de dados da API do Football, você precisa se registrar com eles e obter a chave da API. Requer um cartão, mas se você não fizer mais de 50 solicitações por dia, nada será deduzido dele.
Além disso, você pode executar esse aplicativo online na
seção apropriada do site. Na guia Plataforma, selecione o exemplo de cálculo de probabilidades da UEFA e clique em Reproduzir.
A propósito, se alguém precisar implementar algum sistema simples para o qual o Excel não seja mais adequado, escreva nos comentários. Para conhecer os recursos da plataforma, tentaremos implementá-la e escrever o artigo correspondente.