Estrutura de banco de dados para o jogo 2v2

10

Eu jogo regularmente 2v2 com 12 amigos e quero um banco de dados para acompanhar jogadores, equipes, pontuações e jogos, com a intenção de criar um sistema de classificação.

Como trocamos de time regularmente, eu tenho tabelas players, teamse gamesonde os jogos têm duas equipes (equipe1 e equipe2) e as equipes consistem em dois jogadores (jogador1 e jogador2).

Isso causa alguns problemas - por exemplo, se eu escolher dois jogadores (vamos chamá-los de A e B ) para jogar juntos, tenho que verificar se já existe uma equipe onde o Jogador1 é A e o Jogador2 é B ou o Jogador1 é B e o Jogador2 é um.

As colunas gamese winsestão presentes na playerstabela e na teamstabela - mas isso é porque eu quero ver quantos jogos são vencidos pelos jogadores, mas também como o jogador é compatível em equipes diferentes (com que frequência um jogador vence quando se une a eles) outro jogador específico).

  1. Placar do ranking (provavelmente vou usar o sistema de classificação Elo )
  2. Uma página de estatísticas para cada jogador com classificação, vitórias, jogos, estatísticas de jogos recentes e com quais jogadores ele é mais compatível.

Eu suspeito fortemente que muito disso viola alguns dos princípios da normalização de banco de dados e gostaria de algumas sugestões sobre como implementar o design do meu banco de dados.

Design do Banco de Dados

Daniel
fonte
Eu acho que essa é uma pergunta muito boa. Gostaria de ver sua estrutura de banco de dados atual diagramada na pergunta. Nem todo mundo conhece o Schema Builder do Laravel. Os casos de uso também podem ser melhorados, para entendermos suas reais necessidades.
Candied_orange
Muito obrigado @CandiedOrange - Eu adicionei o diagrama de estrutura DB, e irá adicionar mais casos de uso :)
Daniel
Boa atualização. Eu estaria correto ao supor que cada jogador estará em apenas um time de cada vez e em apenas um jogo por vez? Além disso, os jogadores saem e retornam aos times antigos sem redefinir as informações desse time?
candied_orange
@CandiedOrange Basicamente, quando queremos jogar um jogo, encontramos 4 jogadores (de um total de ~ 12 jogadores) e os agrupamos aleatoriamente em equipes de 2.
Daniel
Não sei dizer se foi sim ou não. Estou tentando entender como o tempo afeta seu design.
candied_orange

Respostas:

2

Há dois problemas que eu vejo no seu esquema atual: um é o problema de ter que verificar dois campos em uma tabela para determinar se uma chave composta é efetivamente uma duplicata e, alguns dados agregados são acumulados nas tabelas individuais para separar entidades (vitórias, especialmente, mas também potencialmente a classificação de um jogador).

Para o primeiro problema, não há truques no DB para fazer com que qualquer campo de uma chave composta seja tratado da maneira OR que você está procurando, mas se o seu DB suportar, você poderá criar uma função getPlayerTeams(player_id)para encapsular A pergunta.

(Você também pode criar uma visualização com o team_thumbprint calculado como um hash dos IDs de jogadores classificados, para que qualquer combinação das mesmas duas pessoas sempre resulte na mesma impressão digital, mas isso pode ser um pouco demais aqui).

Quanto à normalização, considere separar as entidades dos resultados que ocorrem usando uma team_resulttabela para rastrear todos os resultados para uma determinada equipe. Uma normalização um pouco mais extrema também exigiria uma player_rating_histmesa, contendo todas as alterações de classificação para um jogador. A classificação atual é simplesmente aquela com a data mais recente. Uma visualização do player também pode ser usada para conter o valor mais recente para facilitar a consulta.

Esquema proposto (desculpe, não diagrama):

player
    id
    name
    created_on
    updated_on

player_rating_hist
    player_id (FK)
    rating
    rating_date

team
    id
    player1_id (FK)
    player2_id (FK)
    created_on
    updated_on

game
    id
    team1_id (FK)
    team2_id (FK)

team_game
    team_id (FK)
    game_id (FK)
    result
    score
    rating_change

team_rating_hist
    team_id (FK)
    rating
    rating_date

Consultas:

--Results for the game, should only ever be two rows for any given game
SELECT * FROM team_game WHERE game_id = 101

--All results for a team
SELECT * FROM team_game WHERE team_id = 123456 

Essa estrutura permite separar as entidades "base" (jogadores e equipes) do "conteúdo" que ocorre como resultado do funcionamento do sistema ao longo do tempo e significa que você não está atualizando constantemente uma das tabelas base com a classificação atual, # de vitórias, etc. Esses são valores derivados e devem ser recuperados obtendo a classificação mais recente, classificação média, COUNTde vitórias ou perdas, etc. Se o sistema tiver tamanho suficiente, considere extrair esses dados agregados em um "armazém" separado (mesmo que fosse apenas um conjunto separado de tabelas no mesmo banco de dados) para facilitar a análise.

Dan1701
fonte