8
votes

Conception de base de données pour un jeu multijoueur / quiz unique

J'ai vu beaucoup de questions ici, mais personne ne correspond à mon problème. J'essaye de créer un modèle ER évolutif, et si je veux ajouter plus de données ne casse presque rien, donc ce que j'essaye de créer est:

Il y a 2 types d'utilisateurs, disons Admin et Travailleur, et ils ont des rôles différents.

L'administrateur peut faire un CRUD de questions, et peut également créer une salle où les utilisateurs peuvent se joindre pour jouer ensemble (ce n'est qu'un nom, quelque chose comme Kahoot!) mais c'est peut-être une bonne idée de créer plus d'attributs à l'intérieur comme, QUI joue dans cette pièce, des POINTS pour tout le monde mais parlons-en après quand je vous montrerai le design.

Ok, c'est mon design j'ai:

Table User qui contient:

_id
Name
Questions[...]
Then I have to store like a historic about what are the questions worker has answered correct and what did not, to make some statistics, but I need to store some historicals for Admin to see in this topic the average that Workers have failed more is : Question23 (for instance) something like that.

C'est un par défaut, mais alors je me demande comment définir le rôle si c'est un administrateur ou un travailleur, quelque chose comme isAdmin: true et puis je vérifie ce Bool? Ou je peux créer une autre table qui est Role et la connecter à la table User?

Mais peut-être que je dois créer une table pour les deux, je veux dire qu'il y a un administrateur qui a un mot de passe, et quelques fonctionnalités et ensuite est l'utilisateur Worker qui a un autre mot de passe et une autre fonctionnalité.

Ensuite, j'aimerais avoir la table Question où contient:

_id
name
capacity
type (game can be as a group or solo) that's why this attribute
exam (This should be a flag to know if this question is for an exam or not (It can be for EXAM or PRACTISE)
ranking (This is the top X from 1 to X)
don't think if I have to add the winner here because if I get the position 0 from ranking I get the winner...

Puis le Le tableau de la salle doit contenir:

_id
question_name
answers[1,2,3,4]
correctAnswer or answers because it can be multi option chooser
topic
isExamQuestion
dificulty

Il existe également un tableau nommé Sujet, si ma question a un sujet, je peux sélectionner la question par Sujet. Un exemple de sujet devrait être Math afin que l'utilisateur ne puisse faire que des examens ou faire des tests avec des questions de mathématiques.

_id
username
password
date_creation

Ce qui me manque, pourriez-vous essayer de m'aider à le comprendre comment améliorer cette conception?

REMARQUE: J'utilise Spring pour le côté serveur, Angular pour Frontend et Android pour App, je peux tout changer pour travailler plus vite / mieux avec cette base de données.

EDIT

Il y a le déroulement du jeu si vous avez besoin de plus de détails et si je suis mal expliqué.

Flux d'administration

  1. Créez des questions (avec différents types de réponses comme Vrai / Faux, avec des cases à cocher (réponse unique et multi-réponses), du texte, etc ...)
  2. Créez un "jeu" où les travailleurs peuvent se joindre (il s'agit principalement de programmes) mais il devrait s'agir d'une salle avec des attributs, comme id de la salle, maxNumber, type (examen) et stocker les historiques, il y a aussi un type du jeu (par exemple, images, vidéos, etc.)
  3. Voir les statistiques sur les travailleurs, cela signifie voir combien de réponses ils ont répondu correctement, ont échoué, voir par sujet (c'est comme des jointures et des trucs, mais la conception doit être bien faite)
  4. Voir l'historique des examens qu'il a passés auparavant avec toutes les informations (participant, score, temps, trucs)

Et le flux de travail est

Il peut s'entraîner signifie qu'il répond aux questions au hasard ou par sujet (chaque réponse doit être enregistrée pour les statistiques et pour éviter de répéter celles qu'il répond correctement) , aussi il peut faire des examens (pas multijoueurs) juste une option que l'administrateur peut vérifier si la question fait partie d'un examen ou non.

Et puis le truc de la salle, il peut rejoindre avec l'ID. p>

Si vous avez besoin de plus amples éclaircissements, faites-le moi savoir et je vous répondrai dès que possible.


2 commentaires

À quoi ressemble «mieux»? Plus rapide? Plus facile à coder? Plus facile à changer?


Bonjour @NevilleKuyt merci pour votre intérêt, oui depuis le début j'ai quelque chose de similaire au Réponse de MaximFedorov et je cherche une autre solution possible qui pourrait me faire plus évolutive signifie que si je veux ajouter plus de choses, je n'ai pas besoin de changer beaucoup de tables.


3 Réponses :


8
votes

En fait, votre système comporte trois parties logiques (modules):

  • module utilisateurs contenant les données utilisateur et implémentant l'authentification et l'autorisation des actions utilisateur
  • module de questionnaires qui inclut la gestion des questions et des réponses
  • module d’historique des questionnaires contenant l’historique de chaque utilisateur

La conception de la base de données de ces modules peut se présenter comme suit entrez la description de l'image ici

MODULE UTILISATEUR:

rôle - contient les rôles utilisateur dans le système

  • id - identifiant unique du rôle
  • name - le nom du rôle, par exemple, admin, worker, etc.

utilisateur - contient les utilisateurs et des informations sur les rôles qui leur ont été attribués

  • id - identifiant unique de l'utilisateur
  • nom d'utilisateur
  • mot de passe
  • role_id - identifiant que le rôle a été attribué à l'utilisateur

MODULE DE QUESTIONNAIRES:

sujet - contient des thèmes de questions

  • id - identifiant unique du thème
  • nom - un nom du thème

question - contient des questions

  • id - identifiant unique de la question
  • topic_id - identifiant du sujet de la question
  • texte - contenu de la question
  • is_exam_question - question d'examen ou non
  • type - type de réponses (booléen, cases à cocher ou etc.)
  • difficulté

answer - contient toutes les réponses aux questions

  • id - identifiant unique de la réponse
  • question_id - identifiant de la question qui contient la réponse
  • texte - contenu de la question
  • is_correct - indicateur qui signifie que la réponse est vraie ou fausse

salle - contient des informations sur les salles

  • id - identifiant unique du rhum
  • nom - nom du rhum
  • capacité - le nombre maximum de collaborateurs pouvant rejoindre la salle
  • type - type de chambre: groupe, solo ou etc.
  • Learing_type - type de salle: examen, pratique ou etc.

user_in_room - contient des informations sur les utilisateurs qui ont été joints à la salle

  • user_id - identifiant de l'utilisateur qui a rejoint la salle
  • room_id - identifiant de la salle
  • score - score actuel de l'utilisateur dans la salle

MODULE D'HISTOIRE:

user_question_history - contient des informations sur les questions auxquelles l'utilisateur a répondu

  • user_id - identifiant de l'utilisateur
  • room_id - identifiant de la salle où l'utilisateur a répondu aux questions
  • question_id - identifiant de la question à laquelle l'utilisateur a répondu
  • score - score de l'utilisateur à la question

user_answer_history - contient des informations sur les réponses choisies par l'utilisateur

  • user_id - identifiant de l'utilisateur
  • room_id - identifiant de la salle où l'utilisateur a répondu aux questions
  • question_id - identifiant de la question à laquelle l'utilisateur a répondu
  • answer_id - identifiant de la réponse qui a été choisie par l'utilisateur

L'utilisation de ce schéma donne la possibilité de créer différents rapports. Par exemple, vous pouvez afficher le résultat de tous les utilisateurs par salle

SELECT 
    q.text,
    a.text
FROM user_in_room as ur ON ur.room_id = r.id
LEFT JOIN user_question_history as uqh ON ugh.user_id = ur.user_id AND ugh.root_id = ur.room_id
LEFT JOIN question as q ON q.id = ugh.question_id
LEFT JOIN user_answer_history as uah ON uah.user_id = ugh.user_id AND uah.room_id = ugh.room_id AND uah.question_id = ugh.question_id
LEFT JOIN answer as a ON a.id = uah.answer_id
WHERE ur.room_id = <id> AND ur.user_id = <id>

Ou vous pouvez voir des informations détaillées sur les réponses de l'utilisateur

SELECT r.id,
    r.name,
    u.username,
    ur.score
FROM room as r
LEFT JOIN user_in_room as ur ON ur.room_id = r.id
LEFT JOIN user as u ON u.id = ur.user_id
WHERE r.id = <id>


22 commentaires

Merci d'avoir répondu, j'attends plus de propositions, mais je me demande par exemple comment obtenir l'historique des salles?


@ Skizo-ozᴉʞS Quelles données l'historique doit-il contenir?


Imaginez que vous êtes enseignant et que vous passez un examen, il y a 10 jours, vous voulez le vérifier à nouveau, alors que voudriez-vous y voir? Comme les données, le nombre d'élèves qui ont participé, les notes, les réponses à chaque question de chaque élève, etc.


@ Skizo-ozᴉʞS J'ai joint plusieurs questions à la réponse


Génial, laissez-moi jeter un oeil et aller plus loin pour voir s'il manque quelque chose, merci pour votre temps Maxim: D


que pensez-vous de la réponse proposée par TiyebM? Cela a du sens dans votre diagramme?


Si vous supprimez is_correct des réponses et ajoutez la clé de la bonne réponse aux questions, vous pouvez utiliser des contraintes d'intégrité référentielle pour vous assurer que chaque question a une réponse correcte.


@ Skizo-ozᴉʞS Si vous avez besoin de conserver des informations sur votre profil et votre examen, vous pouvez le faire.


@ JamesK.Lowden Oui, vous avez raison, mais une question peut avoir plusieurs bonnes réponses.


Maxim, il me manque quelque chose, il y a une salle qui contient un "examen", dois-je modifier le tableau? Je veux dire que l'administrateur peut créer une salle, alors attribuez-lui un examen à montrer plus tard.


@ Skizo-ozᴉʞS Eh bien, vous devez créer un tableau examen et ajouter un lien vers un examen dans le tableau room


Et c'est une question personnelle, pensez-vous qu'il manque quelque chose dans ma conception? Je veux dire, celui que vous avez fait dans votre réponse pensez-vous qu'il manque quelque chose?


C'est la proposition de type en question, disons que je peux avoir une question pour: examen , étude . quoi de plus


Et maintenant je me demande, si je veux faire différentes questions comme "test", "vrai / faux", "réponse courte" comment ferais-tu cela avec cette conception? Pourriez-vous essayer de me guider s'il vous plaît? (Bien sûr, je mettrai la prime sur votre réponse, mais ce sont des éléments manquants que je me demande)


@ Skizo-ozᴉʞS Si vous souhaitez faire différents types de questions, vous pouvez les définir dans la colonne type (par exemple comme ENUM) et afficher différents champs de saisie qui dépendent de ce type côté client


Alors à partir de maintenant, ça va? Je veux dire que je peux détecter du côté client que la question est une vraie fausse réponse et que la suivante est un test et la suivante est une petite réponse? Je veux dire qu'au moment où l'administrateur crée la question que je peux choisir pour exame si c'est un test, je peux choisir 4 réponses et mettre 1 ou 2 comme une bonne, une? droite?


@ Skizo-ozᴉʞS oui


Merci pour votre effort homme, vraiment, une question si je veux ajouter une explication pour chaque question dois-je mettre un autre paramètre dans le tableau? ou créer une autre table avec le nom d'id etc?


@ Skizo-ozᴉʞS une explication d'une question peut être ajoutée au tableau des questions


user_in_room et history on n'a pas de clé primaire @MaximFedorov? Je crée le schéma pour ceux-ci et je ne vois pas la clé primaire J'ai la possibilité de mettre: NOT NULL PRIMARY KEY UNIQUE < code> FOREIGN KEY et CHECK sont-ils FOREIGN KEY , n'est-ce pas?


@ Skizo-ozᴉʞS user_in_room a user_id et room_id. Ces paramètres identifient un enregistrement. Ces paramètres peuvent être la clé primaire composite.


Existe-t-il un moyen de créer cet ER et d'obtenir les phrases SQL à créer pour postgresql ?? Avez-vous créé l'ER pour la réponse au fait?



1
votes

Vous avez besoin d'une table Profile avec one-to-many with User table, de cette façon si vous souhaitez appliquer un autre privilège, il suffit ajouter une nouvelle entrée de profil:

Table Utilisateur :

 Id
 Name
 Answer(The correct one)
 Id_topic

Table Profil:

 id_exam
 Id_Question
 Answer(provided)
 Id_user(taking the exam)
 IsCorrect(boolean, to avoid farther queries )
 date

Exam et Question sont liées à plusieurs-à-plusieurs , pour le casser, vous en aurez un troisième table Question_Exam:

Question_Exam:

Id
Name
Description

Sujet et Les questions sont le tableau one-to-many

Question :

Id
Username
Fullname
Profile_id
...

L'autre structure est correcte.


0 commentaires

2
votes

Honnêtement, si vous êtes certain que vous n'aurez que des types possibles - à la fois maintenant et dans le futur - un simple booléen isAdmin dans votre table utilisateur fonctionnera parfaitement. Tout le reste de l'administrateur peut être géré du côté de la programmation. Pas besoin de bloquer votre base de données.

Cela dit, s'il y a une petite chance que vous ayez d'autres types d'utilisateurs à l'avenir, la réponse de Maxim est la voie à suivre. De cette façon, l'ajout d'un autre rôle tel que «Éditeur», par exemple, est un simple ajout d'un enregistrement à la table «Rôle». En fait, ajouter 1000 nouveaux types d'utilisateurs est aussi simple que d'ajouter des enregistrements à votre table "Rôle". Comme vous avez déjà une table que vous recherchez pour le rôle, votre code n'a pas à se soucier de tous les types d'utilisateurs possibles (ce qui est pénible si vous en avez beaucoup), seulement de ceux dont il a besoin. La base de données s'occupe du reste.

Un inconvénient de la réponse de Maxim est qu'il faut plus de travail pour implémenter dans la base de données, et plus de travail pour afficher / mettre à jour le rôle de l'utilisateur.

Pour l'implémenter dans la base de données, vous devez créer une table supplémentaire complète et vous assurer qu'elle est correctement liée. Ce n'est pas difficile, mais, surtout si vous êtes nouveau dans dbs, c'est un travail supplémentaire qui ne vaut peut-être pas la peine pour vous. Cela signifie également, du point de vue de la maintenance, que vous avez une autre table sur laquelle garder un œil. Pas grand-chose, mais, encore une fois, il faut réfléchir.

Du côté du code, cela crée également des tâches supplémentaires. D'une part, le type d'utilisateur n'est plus directement dans votre table des utilisateurs - un ID l'est. Cela signifie que lorsque vous souhaitez connaître le nom du type d'utilisateur, vous devrez soit a) interroger la base de données pour ce type d'utilisateur en fonction de l'ID que vous avez, soit b) rejoindre les 2 tables, ce qui peut parfois être délicat. La mise à jour du rôle comporte également des tâches similaires.

Encore une fois, ce ne sont pas des problèmes énormes, juste des choses auxquelles il faut réfléchir. Cela ne vaudra peut-être pas le travail supplémentaire si vous n’avez que deux options possibles.

Donc, en bref, un booléen fonctionnera et est simple à implémenter, mais n'est pas évolutif. La réponse de Maxim est assez évolutive et facilite l'expansion future, mais un peu plus difficile à implémenter et à maintenir. Vous devrez prendre la décision que vous préférez.


1 commentaires

Plus fort. Pas trop dur. Pour l'implémenter, vous aurez besoin de créer une toute autre table ("Rôles") et de la lier correctement, etc. joindre les tables ensemble. Ce n'est pas trop difficile, juste un pas supplémentaire à chaque fois. Je mettrai à jour ma réponse.