# apps/skills/models.py import uuid from django.db import models class SkillTree(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) slug = models.SlugField(max_length=80, unique=True) name = models.CharField(max_length=120) description = models.TextField(blank=True) icon = models.CharField(max_length=80, blank=True) color = models.CharField(max_length=7, blank=True) is_active = models.BooleanField(default=True) sort_order = models.PositiveIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Skill(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) tree = models.ForeignKey( SkillTree, on_delete=models.CASCADE, related_name="skills", ) slug = models.SlugField(max_length=80) name = models.CharField(max_length=120) description = models.TextField(blank=True) icon = models.CharField(max_length=80, blank=True) # Utilisable pour afficher le graphe position_x = models.IntegerField(default=0) position_y = models.IntegerField(default=0) sort_order = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) prerequisites = models.ManyToManyField( "self", symmetrical=False, blank=True, related_name="unlocks", ) class Meta: constraints = [ models.UniqueConstraint( fields=("tree", "slug"), name="unique_skill_slug_per_tree", ) ] class Task(models.Model): class ValidationMode(models.TextChoices): SELF = "self", "Auto-validation" PEER = "peer", "Validation par un tiers" PROOF = "proof", "Preuve demandée" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) slug = models.SlugField(max_length=100, unique=True) name = models.CharField(max_length=160) description = models.TextField(blank=True) base_xp = models.PositiveIntegerField() validation_mode = models.CharField( max_length=16, choices=ValidationMode.choices, default=ValidationMode.SELF, ) cooldown_seconds = models.PositiveIntegerField(default=0) daily_limit = models.PositiveIntegerField(null=True, blank=True) is_repeatable = models.BooleanField(default=True) is_active = models.BooleanField(default=True) skills = models.ManyToManyField( Skill, through="TaskSkillReward", related_name="tasks", ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class TaskSkillReward(models.Model): task = models.ForeignKey(Task, on_delete=models.CASCADE) skill = models.ForeignKey(Skill, on_delete=models.CASCADE) # Permet, par exemple, de répartir 10 XP entre maison et écologie. xp = models.PositiveIntegerField() class Meta: constraints = [ models.UniqueConstraint( fields=("task", "skill"), name="unique_reward_per_task_skill", ) ]