Bonjour,
Je suis présentement dans le processus afin de créer un site web, et je cherche le moyen le plus efficace pour stocker mes données. Je vais donc essayer de décrire la situation le plus brièvement possible, en espérant que le post ne tire pas trop en longueur. Je doute malheureusement qu'il sera aussi court que je l'espère, mais j'ai besoin d'aide pour construire adéquatement ma base de données.
Le projet et les contraintes
Je réalise un site web sur un jeu vidéo. Dans ce jeu vidéo, le joueur incarne un personnage qui peut équiper des objets. Le site web aura deux modules importants : une banque de données pour rechercher les items (objets) et un simulateur de personnage, où l'utilisateur pourra choisir les items à équiper sur son personnage (et le simulateur calculera la somme des attributs, entre autres). Chaque item possédera des attributs (par exemple +5 Endurance).
Les items en général
Tous les objets ne peuvent pas nécessairement être portés par un personnage (exemple: potion). Les items ont par contre tous des points en commun (exemple: ils ont tous un nom), mais certains ont des effets que d'autres n'ont pas. Par exemple, les casques ont des points d'armure, les armes ont des dommages minimaux et maximaux, etc.
Les items normaux
Ces objets servent de base à tous les autres. Ils n'ont pas d'attributs à proprement parler (comme +5 Endurance), mais par exemple, les casques ont des points d'armure même s'ils sont normaux. Ces items se retrouvent en jeu et peuvent être équipés, même s'ils servent de moule aux autres.
Les items magiques et rares
Ce sont des objets normaux auxquels ont été ajoutés des attributs aléatoires (i.e. +5 Endurance). Bref, en plus de ce qui leur est propre (les attributs, voire plus loin), ils héritent de tous les points communs de leur parent (ex. la durabilité d'un objet magique sera la même que la durabilité de son parent qui est un objet normal). Pour donner un exemple, si j'ai un item normal appelé "Knife", il peut exister un item magique appelé "Ornate Knife" qui donne un attribut spécial. Le hic, c'est que ces items sont générés aléatoirement par le jeu : les attributs sont variables et leurs valeurs aussi (un item peut donner +4 Endurance ou +5 Endurance ou encore +4 Énergie). Vu le nombre de possibilités (plusieurs millions de milliards), il n'est pas possible de tous les générer pour les mettre dans la BDD.
Petite précision : tous les items normaux ne peuvent pas nécessairement avoir tous les attributs en même temps. Il y a des règles arbitraires qui font qu'un item a une liste d'attributs possibles plus restreintes.
Les items légendaires
Ce sont des objets normaux auxquels ont été ajoutés des attributs fixes. Ils auront toujours les mêmes attributs, la seule chose qui peut changer est leur valeur. Si un item légendaire donne de l'Endurance, ils donneront toujours de l'Endurance, par contre, un item peut en donner 5 tandis que l'autre va en donner 10 (il y a toujours un minimum et un maximum, donc). Ils héritent aussi des points communs de leur parent, mais ont maintenant un nom fixe. Par exemple, il est possible d'avoir un item appelé "Légendaire #1" qui est une version légendaire de l'objet normal "Casque".
La banque de données
Dans la banque de données, il sera possible de chercher ces items dans la banque (par nom, par attributs, etc.). Ce qui est important à ce niveau, c'est que si l'utilisateur cherche l'item "Légendaire #1", il doit pouvoir trouver tous ses attributs ainsi que les valeurs possibles. Si cet item donne entre +5 et +10 d'Endurance, ce doit être indiqué. Pour les items légendaires, les attributs sont toujours fixes, donc c'est plus simple.
Pour les items rares et magiques, comme ils sont créés aléatoirement par le jeu, c'est plus délicats. En fait, l'utilisateur pourra chercher un item normal, et il devrait s'afficher la liste des attributs possibles et la plage de valeurs qu'ils peuvent prendre que cet item normal peut avoir s'il est magique ou rare.
Le simulateur de personnages
L'utilisateur peut choisir les items qu'il veut, avec les attributs qu'il veut. Cela veut donc dire que s'il choisit un item légendaire, il peut choisir que l'attribut Endurance, qui prend une valeur entre 5 et 10, vaut 7. Il peut aussi ne pas spécifier de valeur, dans quel cas le simulateur va faire deux sommes des stats : celle dans le cas où la valeur serait minimale et celle si elle était maximale.
Ça devient un peu plus corsé pour les items magiques et rares. Comme ces items ont des attributs variables, l'utilisateur peut choisir un item normal et lui donner tous les attributs qu'il souhaite parmi ceux que l'item normal peut avoir (règles arbitraires données par le jeu). Il peut aussi (c'est facultatif comme les items légendaires, il peut laisser la plage disponible) fixer une valeur à un attribut.
Une fois que l'utilisateur a choisi ses items, je dois donc les enregistrer dans la base de données, en sachant que certains attributs peuvent être fixés ou non.
Résumé rapide
Il y a donc des items normaux qui servent de base à tous les autres items. Il y a des items magiques et rares qui prennent des attributs et des valeurs variables, et des items légendaires qui ont toujours les mêmes attributs, mais la valeur de ceux-ci peut être variable.
Je dois trouver un moyen pour :
A) Stocker les items pour qu'ils puissent être recherchés adéquatement par l'utilisateur selon divers critères;
B) Permettre aux utilisateurs de faire leurs items personnels pour le simulateur de perso.
Les données techniques
Je tiens à préciser que je n'ai jamais reçu de formation quelconque. La programmation est une de mes passions et je suis naturellement curieux, donc au fil du temps, j'ai appris certaines bonnes et mauvaises pratiques. Je ne suis pas un vrai débutant, mais je suis loin d'être un expert dans le domaine. Ceci étant dit, je ne connais malheureusement pas les termes techniques du domaine (c'est pourquoi il n'y a pas de préfixe dans mon titre) et je n'ai jamais utilisé d'outils pour créer de jolis schémas comme j'en vois ici. Je décris plutôt la structure des tables directement.
Je vais donc utiliser PostgreSQL 9.0.4 (avec Python et Django, mais je doute que ce soit nécessaire de le mentionner ici). Je vais enlever certains détails qui ne sont pas importants à ce qui me pose problème pour aller au vif du sujet. J'ai préfixé d'un @ les colonnes qui font référence à une table qui n'est pas utile de nommer. Grosso modo, voici comment je vois la chose :
attribute [attr_id, attr_name]
item [item_id, item_name, @item_type_id (casque, arme...), @item_quality_id (normal, légendaire...)]
item_attr [@item_id, @attr_id, min_value (valeur minimale que la stat peut prendre pour l'item), max_value (idem)]
Il y aura donc, pour un item, autant de lignes qu'il y a d'attributs, et la table de liaison item_attr permettra de donner la valeur minimale et maximale qu'un attribut peut prendre.
Problème #1
Comme je l'ai dit plus haut, certains items ont des attributs qui leur sont spécifiques (ex. les c asques ont des points d'armure). J'avais prévu utiliser l'héritage que fourni PGSQL, mais je me suis rendu compte qu'une FK sur la table parent ne s'étend pas jusqu'aux enfants, ce qui rendait la solution inutilisable si je souhaite conserver l'intégrité référentielle. Je vois donc deux solutions :
1) On oublie l'intégrité référentielle et on fait de l'héritage
2) On ajoute des tonnes de colonnes à la table item, qui seront NULL si la colonne ne s'applique pas pour un item (les armes n'ont pas de points d'armure => NULL). Je penche pour celle-ci.
Y a-t-il une autre option qui s'offre à moi ? J'ai pensé à convertir certains points spécifiques en attribut (genre que les points d'armure soient un attribut plutôt qu'un point spécifique à un item). Si ça semble logique dans ce cas-ci, ça ne l'est pas pour tous. Par exemple, une arme aura une classe (ex. une arme peut être une hache, un bâton, etc.), ce qui ne se transpose pas très bien en attribut.
Ensuite, les items personnels des utilisateurs. Il y a deux cas possibles :
1) On prend un item légendaire dans la table item et on lui donne des valeurs spécifiques ou pas
2) On prend un item normal dans la table item et on lui donne des attributs et des valeurs spécifiques ou pas
Le pattern est similaire. Je dois donc trouver un moyen efficace de stocker ces informations, de préférence en essayant d'éviter les doublons (deux utilisateurs différents créent le même item avec les mêmes attributs et les mêmes valeurs => une seule entrée pour les deux). J'avais pensé à un truc dans le genre :
custom_item [custom_item_id, @item_id]
custom_item_attr [@custom_item_id, @attr_id, min_value, max_value]
profile_items [@profile_id, @custom_item_id]
L'utilisateur choisit donc son item, et s'il choisit des attributs ou valeurs personnalisés, ceux-ci sont privilégiés par rapport à ceux que l'item de base a habituellement. On ne remet pas tous les attributs de l'item, seulement ceux qui ne sont pas par défaut.
Problème #2
Est-ce une solution envisageable ? Je vais devoir ajouter tous les items de l'utilisateur dans la table custom_item même s'ils ne sont pas modifiés, mais je n'ai pas trouvé de meilleures solutions.
Conclusion
Ce sont les deux principaux problèmes qui m'empêchent d'avancer présentement. Enfin, les seuls auxquels je pense présentement, il est fort probable que j'aie encore besoin d'aide plus tard. Je suis conscient que mon post est très long et c'est une de mes peurs : que je n'aie pas de réponses parce que les gens ne veulent pas lire autant. J'ai essayé de réduire à l'essentiel (croyez-moi, je pourrais en dire beaucoup plus), mais même si mes problèmes sont d'apparence simples, ils nécessitent de connaître l'information derrière.
Ensuite, je ne suis pas persuadé que je poste au bon endroit. Il y a tellement de forums sur DVP que je ne sais plus où donner de la tête. C'est ici que semblait être le forum approprié, mais si ce n'est pas le cas, n'hésitez pas à déplacer (ou je peux refaire un nouveau sujet). Je sais que je ne fournis pas de beaux schémas et que je n'utilise pas de termes techniques propres à ce forum, mais je fais mon possible.
Dernière chose : ça me paraît clair parce que je sais de quoi je parle, mais n'hésitez pas à demander des précisions si c'est nécessaire, je me ferai un plaisir de les apporter.
Merci beaucoup de m'avoir lu, c'est très, très apprécié, et merci d'avance pour les futures réponses.
Jihnn
Partager