Перейти до змісту

МОДЕЛІ

ER-діаграма

📍 SETTINGS, USERS, PROFILE

📋UserSettings

📋UserProfile

📍CATEGORIES, WORD VOCABULARIES MODELS

📋💾 WordCategory, WordSubCategory

  • можна імпортувати / експортувати з файла ексель через адмiнку проекту

models.py

class WordCategory(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(
        max_length=255,
        unique=True,
        # default='БЕЗ КАТЕГОРІЇ',
        verbose_name="Категорія"
        )
    class Meta:
        verbose_name = "Категорія слова"
        verbose_name_plural = "Категорії слів"

    def __str__(self):
        return self.name

class WordSubcategory(models.Model):
    id = models.IntegerField(primary_key=True)
    category = models.ForeignKey(
        WordCategory,
        on_delete=models.CASCADE,
        related_name='subcategories')
    name = models.CharField(max_length=255, verbose_name="Підкатегорія")

    class Meta:
        verbose_name = "Підкатегорія слова"
        verbose_name_plural = "Підкатегорії слів"

    def __str__(self):
        return self.name

def get_default_category():
    default_category, _ = WordCategory.objects.get_or_create(name="БЕЗ КАТЕГОРІЇ")
    return default_category.id

def get_default_subcategory():
    # Беремо дефолтну категорію
    default_category, _ = WordCategory.objects.get_or_create(name="БЕЗ КАТЕГОРІЇ")

    # Беремо дефолтну підкатегорію, яка належить до дефолтної категорії
    default_subcategory, _ = WordSubcategory.objects.get_or_create(
        name="БЕЗ ПІДКАТЕГОРІЇ",
        category=default_category
    )

    return default_subcategory.id  # повертаємо id для ForeignKey

admin.py

class WordCategoryResource(resources.ModelResource):
    class Meta:
        model = WordCategory
        fields = ('id', 'name')
        import_id_fields = ('id',)

class WordSubcategoryResource(resources.ModelResource):
    category = fields.Field(
        column_name='category_name',
        attribute='category',
        widget=ForeignKeyWidget(WordCategory, 'name')  # шукає категорію по name
    )

    class Meta:
        model = WordSubcategory
        fields = ('id', 'name', 'category')
        import_id_fields = ('id',)

class WordSubcategoryInline(admin.TabularInline):  # або StackedInline
    model = WordSubcategory
    extra = 1  # кількість порожніх рядків для додавання нових

@admin.register(WordCategory)
class WordCategoryAdmin(ImportExportModelAdmin):
    resource_class = WordCategoryResource

    list_display = ("id", "name")
    search_fields = ('name',)
    list_editable = ('name',)

    inlines = [WordSubcategoryInline]  # додаємо inline


@admin.register(WordSubcategory)
class WordSubcategoryAdmin(ImportExportModelAdmin):
    resource_class = WordSubcategoryResource

    list_display = ("id", "name", "category")
    search_fields = ('name',)
    list_editable = ('name',)
    list_filter = ("category",)

📋WordSubcategory

📋UserCustomWord

📋💾Word

  • можна імпортувати / експортувати з файла ексель через адмiнку проекту

📋UserWordsProgress

📋💾 WordDeutch

  • можна імпортувати / експортувати з файла ексель через адмiнку проекту

📋UserWordsDeutchProgress

📍GAME MODELS

📋PlayerProfile

📋💾 BossProfile

  • можна імпортувати / експортувати з файла ексель через адмiнку проекту

models.py

class BossProfile(models.Model):
    name = models.CharField(max_length=200, blank=True)
    level = models.IntegerField(default=0)

    # #abilities
    strength = models.IntegerField(default=1)
    dexterity = models.IntegerField(default=1)
    intelligence = models.IntegerField(default=1)

    # #characteristics
    damage_physical = models.IntegerField(default=10) # strength
    hitpoints = models.IntegerField(default=100) # strength
    endurance = models.IntegerField(default=100)

    damage_magical = models.IntegerField(default=10) # intelligence
    mana = models.IntegerField(default=10) # intelligence

    dodge = models.FloatField(default=0) #dexterity
    accuracy = models.IntegerField(null=True, blank=True)
    critical_chance = models.FloatField(default=0) #dexterity

    #defence
    armor = models.IntegerField(default=0)
    defence_fire = models.IntegerField(default=0)
    defence_water = models.IntegerField(default=0)
    defence_earth = models.IntegerField(default=0)
    defence_wind = models.IntegerField(default=0)

admin.py

class BossProfileResource(resources.ModelResource):
    class Meta:
        model = BossProfile
        fields = (
        'id',
        'name', 'level', 'strength', 'dexterity', 'intelligence',
        'damage_physical', 'endurance', 'hitpoints',
        'damage_magical', 'mana',
        'dodge', 'critical_chance', 'accuracy',
        'armor', 'defence_fire', 'defence_earth', 'defence_water', 'defence_wind',
    )

        export_order = fields

        import_id_fields = ("id",)  
        """означає, що під час імпорту система буде шукати існуючі записи у базі за полем id.
            Якщо запис з таким id існує → він оновлюється. 
            Якщо запису з таким id немає → створюється новий запис."""


@admin.register(BossProfile)
class BossProfileAdmin(ImportExportModelAdmin):
    resource_class = BossProfileResource
    list_display = (
        'id',
        'name', 'level', 'strength', 'dexterity', 'intelligence',
        'damage_physical', 'endurance', 'hitpoints',
        'damage_magical', 'mana',
        'dodge', 'critical_chance', 'accuracy',
        'armor', 'defence_fire', 'defence_earth', 'defence_water', 'defence_wind',
    )

    list_editable = (
        'level', 'strength', 'dexterity', 'intelligence',
        'damage_physical', 'endurance', 'hitpoints',
        'damage_magical', 'mana',
        'dodge', 'critical_chance', 'accuracy',
        'armor', 'defence_fire', 'defence_earth', 'defence_water', 'defence_wind',
    )

    list_filter = ('level', 'strength', 'dexterity', 'intelligence', 'name')
    search_fields = ('name',)

📋💾 Skill

  • можна імпортувати / експортувати з файла ексель через адмунку проекту

models.py

class Skill(models.Model):
    SKILL_TYPES = [
        ("PHYSICAL_DAMAGE", "Physical damage"),
        ("PHYSICAL_DEFENCE", "Physical defence"),
        ("MAGICAL_DAMAGE", 'Magical damage'),
        ("MAGICAL_DEFENCE", "Magical defence"),
        ('BUFF', 'Buff'),
        ('HEALING', 'Healing')         
    ]
    id = models.IntegerField(primary_key=True)
    type = models.CharField(max_length=20, choices=SKILL_TYPES)
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True)

    # cost
    mana_cost = models.IntegerField(default=0)
    endurance_cost = models.IntegerField(default=0)

    #damage
    damage_physical = models.IntegerField(default=0)
    damage_fire = models.IntegerField(default=0)
    damage_water = models.IntegerField(default=0)
    damage_earth = models.IntegerField(default=0)
    damage_wind = models.IntegerField(default=0)
    # buffs

    def __str__(self):
        return self.name

admin.py

class SkillResource(resources.ModelResource):
    class Meta:
        model = Skill
        fields = (
            'id',
        'type', 'name', 'description',
        'endurance_cost','damage_physical', 
        'mana_cost', 'damage_fire', 'damage_water', 'damage_earth', 'damage_wind',
        )

        export_order = fields

        import_id_fields = ("id",)  
        """означає, що під час імпорту система буде шукати існуючі записи у базі за полем id.
            Якщо запис з таким id існує → він оновлюється. 
            Якщо запису з таким id немає → створюється новий запис."""

@admin.register(Skill)
class SkillAdmin(ImportExportModelAdmin):
    resource_class = SkillResource

    formfield_overrides = {
        models.CharField: {'widget': TextInput(attrs={'style': 'width: 50px;'})},
        models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':20})},
    }

    list_display = (
        'id',
        'type', 'name', 'description',
        'endurance_cost','damage_physical', 
        'mana_cost', 'damage_fire', 'damage_water', 'damage_earth', 'damage_wind',  )
    list_editable = ( 'type', 'name', 'description',
        'endurance_cost','damage_physical', 
        'mana_cost', 'damage_fire', 'damage_water', 'damage_earth', 'damage_wind',)

📋PlayerSkill

📋Items

class Items(models.Model):
    ITEM_TYPES = [
        ("ARMOR", "Armor"),
        ("WEAPON", "Weapon"),
        ("USABLE", 'Usable'),
        ("SHIELD", "Shield"),            
    ]

    name = models.CharField(max_length=100)
    item_type = models.CharField(max_length=10, choices=ITEM_TYPES)
    price = models.IntegerField(default=0)

    # характеристики для броні
    armor = models.IntegerField(null=True, blank=True)
    defence_fire = models.IntegerField(null=True, blank=True)
    defence_earth = models.IntegerField(null=True, blank=True)

    # характеристики для зброї
    damage = models.IntegerField(null=True, blank=True)
    is_damage_physical = models.BooleanField(default=False)
    is_damage_magical = models.BooleanField(default=False)
    is_damage_ice = models.BooleanField(default=False)
    is_damage_earth = models.BooleanField(default=False)

    accuracy = models.IntegerField(null=True, blank=True)

📋Battle

class Battle(models.Model):
    BATTLE_TYPES = [
        ('PVE', 'Player vs Environment'),
        ('PVP', 'Player vs Player')
    ]
    #battle_info
    battle_type = models.CharField(max_length=3, choices=BATTLE_TYPES)
    player_1 = models.ForeignKey(PlayerProfile, null=True, blank=True, on_delete=models.CASCADE, related_name='battles_as_player1')

    player_2 = models.ForeignKey(PlayerProfile, null=True, blank=True, on_delete=models.CASCADE, related_name='battles_as_player2')

    boss = models.ForeignKey(BossProfile, null=True, blank=True, on_delete=models.CASCADE)

    battle_status = models.IntegerField(default=0)

    # battle statuses
    is_active = models.BooleanField(default=True)

    # ROUND
    round_status = models.IntegerField(default=0)
    round_number = models.IntegerField(default=1)
    player_1_finished_round = models.BooleanField(default=False)
    player_2_finished_round = models.BooleanField(default=False)
    notified_player = models.ForeignKey(PlayerProfile, null=True, blank=True, on_delete=models.CASCADE)
    winner = models.ForeignKey(PlayerProfile, on_delete=models.CASCADE, related_name='winner', null=True)

📋BattleTurn

class BattleTurn(models.Model):
    player_profile = models.ForeignKey(PlayerProfile, on_delete=models.CASCADE, related_name='battle_turn')
    battle = models.ForeignKey(Battle, on_delete=models.CASCADE, related_name='battle_turn')
    round_number = models.IntegerField(default=1)

    # player_choice
    player_attack = models.IntegerField(default=0)
    enemy_attack = models.IntegerField(default=0)
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE)

    created_at = models.DateTimeField(auto_now_add=True)
    processed = models.BooleanField(default=False)

📋

📋

📋

📋