diff --git a/LctMonolith/Database/Data/AppDbContext.cs b/LctMonolith/Database/Data/AppDbContext.cs index 3cc103c..9e27cab 100644 --- a/LctMonolith/Database/Data/AppDbContext.cs +++ b/LctMonolith/Database/Data/AppDbContext.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using LctMonolith.Models.Database; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; @@ -12,28 +11,36 @@ namespace LctMonolith.Database.Data; /// public class AppDbContext : IdentityDbContext, Guid> { - public AppDbContext(DbContextOptions options) : base(options) { } + // Rank related entities public DbSet Ranks => Set(); - public DbSet RankRequiredMissions => Set(); - public DbSet RankRequiredCompetencies => Set(); + public DbSet RankMissionRules => Set(); + public DbSet RankSkillRules => Set(); + // Mission related entities + public DbSet MissionCategories => Set(); public DbSet Missions => Set(); - public DbSet UserMissions => Set(); - public DbSet MissionCompetencyRewards => Set(); - public DbSet MissionArtifactRewards => Set(); + public DbSet PlayerMissions => Set(); + public DbSet MissionSkillRewards => Set(); + public DbSet MissionItemRewards => Set(); + public DbSet MissionRankRules => Set(); - public DbSet Competencies => Set(); - public DbSet UserCompetencies => Set(); + // Skill related entities + public DbSet Skills => Set(); + public DbSet PlayerSkills => Set(); - public DbSet Artifacts => Set(); - public DbSet UserArtifacts => Set(); + // Dialogue related entities + public DbSet Dialogues => Set(); + public DbSet DialogueMessages => Set(); + public DbSet DialogueMessageResponseOptions => Set(); + // Store and inventory public DbSet StoreItems => Set(); public DbSet UserInventoryItems => Set(); public DbSet Transactions => Set(); + // System entities public DbSet EventLogs => Set(); public DbSet RefreshTokens => Set(); public DbSet Notifications => Set(); @@ -42,54 +49,160 @@ public class AppDbContext : IdentityDbContext, Guid> { base.OnModelCreating(b); - // Rank required mission composite key - b.Entity().HasKey(x => new { x.RankId, x.MissionId }); - b.Entity() - .HasOne(x => x.Rank).WithMany(r => r.RequiredMissions).HasForeignKey(x => x.RankId); - b.Entity() - .HasOne(x => x.Mission).WithMany(m => m.RanksRequiring).HasForeignKey(x => x.MissionId); + // Rank configurations + b.Entity() + .HasIndex(r => r.ExpNeeded) + .IsUnique(); + b.Entity() + .HasIndex(r => r.Title) + .IsUnique(); - // Rank required competency composite key - b.Entity().HasKey(x => new { x.RankId, x.CompetencyId }); - b.Entity() - .HasOne(x => x.Rank).WithMany(r => r.RequiredCompetencies).HasForeignKey(x => x.RankId); - b.Entity() - .HasOne(x => x.Competency).WithMany(c => c.RankRequirements).HasForeignKey(x => x.CompetencyId); + // Skill configurations + b.Entity() + .HasIndex(s => s.Title) + .IsUnique(); - // UserMission composite key - b.Entity().HasKey(x => new { x.UserId, x.MissionId }); - b.Entity() - .HasOne(x => x.User).WithMany(u => u.Missions).HasForeignKey(x => x.UserId); - b.Entity() - .HasOne(x => x.Mission).WithMany(m => m.UserMissions).HasForeignKey(x => x.MissionId); + // MissionCategory configurations + b.Entity() + .HasIndex(mc => mc.Title) + .IsUnique(); - // UserCompetency composite key - b.Entity().HasKey(x => new { x.UserId, x.CompetencyId }); - b.Entity() - .HasOne(x => x.User).WithMany(u => u.Competencies).HasForeignKey(x => x.UserId); - b.Entity() - .HasOne(x => x.Competency).WithMany(c => c.UserCompetencies).HasForeignKey(x => x.CompetencyId); + // Mission configurations + b.Entity() + .HasOne(m => m.MissionCategory) + .WithMany(mc => mc.Missions) + .HasForeignKey(m => m.MissionCategoryId) + .IsRequired(); + b.Entity() + .HasOne(m => m.ParentMission) + .WithMany(m => m.ChildMissions) + .HasForeignKey(m => m.ParentMissionId) + .IsRequired(false); + // Dialogue relationship for Mission + b.Entity() + .HasOne(m => m.Dialogue) + .WithOne(d => d.Mission) + .HasForeignKey(m => m.DialogueId) + .IsRequired(false); - // Mission competency reward composite key - b.Entity().HasKey(x => new { x.MissionId, x.CompetencyId }); + // MissionRankRule configurations + b.Entity() + .HasOne(mrr => mrr.Mission) + .WithMany(m => m.MissionRankRules) + .HasForeignKey(mrr => mrr.MissionId); + b.Entity() + .HasOne(mrr => mrr.Rank) + .WithMany(r => r.MissionRankRules) + .HasForeignKey(mrr => mrr.RankId); - // Mission artifact reward composite key - b.Entity().HasKey(x => new { x.MissionId, x.ArtifactId }); + // MissionSkillReward configurations + b.Entity() + .HasKey(x => new { x.MissionId, x.SkillId }); + b.Entity() + .HasOne(msr => msr.Mission) + .WithMany(m => m.MissionSkillRewards) + .HasForeignKey(msr => msr.MissionId); + b.Entity() + .HasOne(msr => msr.Skill) + .WithMany(s => s.MissionSkillRewards) + .HasForeignKey(msr => msr.SkillId); - // UserArtifact composite key - b.Entity().HasKey(x => new { x.UserId, x.ArtifactId }); + // MissionItemReward configurations + b.Entity() + .HasOne(mir => mir.Mission) + .WithMany(m => m.MissionItemRewards) + .HasForeignKey(mir => mir.MissionId); - // UserInventory composite key - b.Entity().HasKey(x => new { x.UserId, x.StoreItemId }); + // RankMissionRule composite key + b.Entity().HasKey(x => new { x.RankId, x.MissionId }); + b.Entity() + .HasOne(rmr => rmr.Rank) + .WithMany(r => r.RankMissionRules) + .HasForeignKey(rmr => rmr.RankId); + b.Entity() + .HasOne(rmr => rmr.Mission) + .WithMany(m => m.RankMissionRules) + .HasForeignKey(rmr => rmr.MissionId); + + // RankSkillRule composite key + b.Entity().HasKey(x => new { x.RankId, x.SkillId }); + b.Entity() + .HasOne(rsr => rsr.Rank) + .WithMany(r => r.RankSkillRules) + .HasForeignKey(rsr => rsr.RankId); + b.Entity() + .HasOne(rsr => rsr.Skill) + .WithMany(s => s.RankSkillRules) + .HasForeignKey(rsr => rsr.SkillId); + + // PlayerSkill composite key + b.Entity().HasKey(x => new { x.PlayerId, x.SkillId }); + b.Entity() + .HasOne(ps => ps.Player) + .WithMany(p => p.PlayerSkills) + .HasForeignKey(ps => ps.PlayerId); + b.Entity() + .HasOne(ps => ps.Skill) + .WithMany(s => s.PlayerSkills) + .HasForeignKey(ps => ps.SkillId); + + // PlayerMission composite key + b.Entity().HasKey(x => new { x.PlayerId, x.MissionId }); + b.Entity() + .HasOne(pm => pm.Player) + .WithMany(p => p.PlayerMissions) + .HasForeignKey(pm => pm.PlayerId); + b.Entity() + .HasOne(pm => pm.Mission) + .WithMany(m => m.PlayerMissions) + .HasForeignKey(pm => pm.MissionId); + + // Dialogue configurations + b.Entity() + .HasOne(d => d.Mission) + .WithOne(m => m.Dialogue) + .HasForeignKey(d => d.MissionId) + .IsRequired(); + + // DialogueMessage configurations + b.Entity() + .HasOne(dm => dm.InitialDialogue) + .WithMany() + .HasForeignKey(dm => dm.InitialDialogueId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); + b.Entity() + .HasOne(dm => dm.InterimDialogue) + .WithMany() + .HasForeignKey(dm => dm.InterimDialogueId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); + b.Entity() + .HasOne(dm => dm.EndDialogue) + .WithMany() + .HasForeignKey(dm => dm.EndDialogueId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); + + // DialogueMessageResponseOption configurations + b.Entity() + .HasOne(dmro => dmro.ParentDialogueMessage) + .WithMany(dm => dm.DialogueMessageResponseOptions) + .HasForeignKey(dmro => dmro.ParentDialogueMessageId) + .IsRequired(); + b.Entity() + .HasOne(dmro => dmro.DestinationDialogueMessage) + .WithMany() + .HasForeignKey(dmro => dmro.DestinationDialogueMessageId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Restrict); // Refresh token index unique b.Entity().HasIndex(x => x.Token).IsUnique(); - // ---------- Added performance indexes ---------- + // ---------- Performance indexes ---------- b.Entity().HasIndex(u => u.RankId); - b.Entity().HasIndex(m => m.MinRankId); - b.Entity().HasIndex(um => new { um.UserId, um.Status }); - b.Entity().HasIndex(uc => uc.CompetencyId); // for querying all users by competency + b.Entity().HasIndex(ps => ps.SkillId); b.Entity().HasIndex(e => new { e.UserId, e.Type, e.CreatedAt }); b.Entity().HasIndex(i => i.IsActive); b.Entity().HasIndex(t => new { t.UserId, t.CreatedAt });