using Microsoft.EntityFrameworkCore; using RR3CommunityServer.Models; namespace RR3CommunityServer.Data; public class RR3DbContext : DbContext { public RR3DbContext(DbContextOptions options) : base(options) { } public DbSet Devices { get; set; } public DbSet Users { get; set; } public DbSet Sessions { get; set; } public DbSet Accounts { get; set; } public DbSet DeviceAccounts { get; set; } public DbSet Purchases { get; set; } public DbSet CatalogItems { get; set; } public DbSet DailyRewards { get; set; } public DbSet TimeTrials { get; set; } public DbSet TimeTrialResults { get; set; } public DbSet Cars { get; set; } public DbSet OwnedCars { get; set; } public DbSet CarUpgrades { get; set; } public DbSet CareerProgress { get; set; } public DbSet GameAssets { get; set; } public DbSet ModPacks { get; set; } public DbSet UserSettings { get; set; } public DbSet PlayerSaves { get; set; } public DbSet LeaderboardEntries { get; set; } public DbSet PersonalRecords { get; set; } public DbSet Events { get; set; } public DbSet EventCompletions { get; set; } public DbSet EventAttempts { get; set; } public DbSet Notifications { get; set; } public DbSet Friends { get; set; } public DbSet FriendInvitations { get; set; } public DbSet Gifts { get; set; } public DbSet Clubs { get; set; } public DbSet ClubMembers { get; set; } public DbSet MatchmakingQueues { get; set; } public DbSet RaceSessions { get; set; } public DbSet RaceParticipants { get; set; } public DbSet GhostData { get; set; } public DbSet CompetitiveRatings { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // Seed some default catalog items modelBuilder.Entity().HasData( new CatalogItem { Id = 1, Sku = "com.ea.rr3.gold_1000", Name = "1000 Gold", Type = "currency", Price = 0.99m, Available = true }, new CatalogItem { Id = 2, Sku = "com.ea.rr3.car_tier1", Name = "Starter Car", Type = "car", Price = 0m, Available = true }, new CatalogItem { Id = 3, Sku = "com.ea.rr3.upgrade_engine", Name = "Engine Upgrade", Type = "upgrade", Price = 4.99m, Available = true } ); // Seed gold purchase options modelBuilder.Entity().HasData( new CatalogItem { Id = 4, Sku = "com.ea.rr3.gold_100", Name = "100 Gold", Type = "currency", Price = 0m, // FREE in community server Available = true }, new CatalogItem { Id = 5, Sku = "com.ea.rr3.gold_500", Name = "500 Gold", Type = "currency", Price = 0m, Available = true }, new CatalogItem { Id = 6, Sku = "com.ea.rr3.gold_1000", Name = "1000 Gold", Type = "currency", Price = 0m, Available = true }, new CatalogItem { Id = 7, Sku = "com.ea.rr3.gold_5000", Name = "5000 Gold", Type = "currency", Price = 0m, Available = true } ); // Seed time trials modelBuilder.Entity().HasData( new TimeTrial { Id = 1, Name = "Daily Sprint Challenge", TrackName = "Silverstone National", CarName = "Any Car", StartDate = DateTime.UtcNow, EndDate = DateTime.UtcNow.AddDays(7), TargetTime = 90.5, GoldReward = 50, CashReward = 10000, Active = true }, new TimeTrial { Id = 2, Name = "Speed Demon Trial", TrackName = "Dubai Autodrome", CarName = "Any Car", StartDate = DateTime.UtcNow, EndDate = DateTime.UtcNow.AddDays(7), TargetTime = 120.0, GoldReward = 100, CashReward = 25000, Active = true } ); // Seed starter cars modelBuilder.Entity().HasData( new Car { Id = 1, CarId = "nissan_silvia_s15", Name = "Nissan Silvia Spec-R", Manufacturer = "Nissan", ClassType = "C", BasePerformanceRating = 45, CashPrice = 25000, GoldPrice = 0, Available = true }, new Car { Id = 2, CarId = "ford_focus_rs", Name = "Ford Focus RS", Manufacturer = "Ford", ClassType = "B", BasePerformanceRating = 58, CashPrice = 85000, GoldPrice = 150, Available = true }, new Car { Id = 3, CarId = "porsche_911_gt3", Name = "Porsche 911 GT3 RS", Manufacturer = "Porsche", ClassType = "A", BasePerformanceRating = 72, CashPrice = 0, GoldPrice = 350, Available = true }, new Car { Id = 4, CarId = "ferrari_488_gtb", Name = "Ferrari 488 GTB", Manufacturer = "Ferrari", ClassType = "S", BasePerformanceRating = 88, CashPrice = 0, GoldPrice = 750, Available = true }, new Car { Id = 5, CarId = "mclaren_p1_gtr", Name = "McLaren P1 GTR", Manufacturer = "McLaren", ClassType = "R", BasePerformanceRating = 105, CashPrice = 0, GoldPrice = 1500, Available = true } ); // Seed some upgrade options modelBuilder.Entity().HasData( // Nissan Silvia upgrades new CarUpgrade { Id = 1, CarId = "nissan_silvia_s15", UpgradeType = "engine", Level = 1, CashCost = 5000, PerformanceIncrease = 3 }, new CarUpgrade { Id = 2, CarId = "nissan_silvia_s15", UpgradeType = "tires", Level = 1, CashCost = 3000, PerformanceIncrease = 2 }, new CarUpgrade { Id = 3, CarId = "nissan_silvia_s15", UpgradeType = "suspension", Level = 1, CashCost = 4000, PerformanceIncrease = 2 }, new CarUpgrade { Id = 4, CarId = "nissan_silvia_s15", UpgradeType = "brakes", Level = 1, CashCost = 3500, PerformanceIncrease = 2 }, new CarUpgrade { Id = 5, CarId = "nissan_silvia_s15", UpgradeType = "drivetrain", Level = 1, CashCost = 4500, PerformanceIncrease = 3 } ); } } // Database entities public class Device { public int Id { get; set; } public string DeviceId { get; set; } = string.Empty; public string HardwareId { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime LastSeenAt { get; set; } = DateTime.UtcNow; } public class User { public int Id { get; set; } public string SynergyId { get; set; } = string.Empty; public string? DeviceId { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public string? Nickname { get; set; } public int? Gold { get; set; } = 0; public int? Cash { get; set; } = 0; public int? Level { get; set; } = 1; public int? Experience { get; set; } = 0; public int? Reputation { get; set; } = 0; // Navigation properties public List OwnedCars { get; set; } = new(); public List CareerProgress { get; set; } = new(); } public class Session { public int Id { get; set; } public string SessionId { get; set; } = string.Empty; public string? SynergyId { get; set; } public string DeviceId { get; set; } = string.Empty; public int? UserId { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime ExpiresAt { get; set; } } public class Purchase { public int Id { get; set; } public string SynergyId { get; set; } = string.Empty; public string ItemId { get; set; } = string.Empty; public string Sku { get; set; } = string.Empty; public string OrderId { get; set; } = string.Empty; public DateTime PurchaseTime { get; set; } = DateTime.UtcNow; public string Token { get; set; } = string.Empty; public decimal Price { get; set; } public string Status { get; set; } = "approved"; // For web panel display public int? UserId { get; set; } public DateTime PurchaseDate => PurchaseTime; } public class CatalogItem { public int Id { get; set; } public string Sku { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Type { get; set; } = string.Empty; public decimal Price { get; set; } public bool Available { get; set; } = true; } public class DailyReward { public int Id { get; set; } public int UserId { get; set; } public DateTime RewardDate { get; set; } public int GoldAmount { get; set; } public int CashAmount { get; set; } public bool Claimed { get; set; } public DateTime? ClaimedAt { get; set; } public int Streak { get; set; } } public class TimeTrial { public int Id { get; set; } public string Name { get; set; } = string.Empty; public string TrackName { get; set; } = string.Empty; public string CarName { get; set; } = string.Empty; public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public double TargetTime { get; set; } public int GoldReward { get; set; } public int CashReward { get; set; } public bool Active { get; set; } = true; } public class TimeTrialResult { public int Id { get; set; } public int UserId { get; set; } public int TimeTrialId { get; set; } public double TimeSeconds { get; set; } public DateTime SubmittedAt { get; set; } public bool BeatTarget { get; set; } public int GoldEarned { get; set; } public int CashEarned { get; set; } // Navigation properties public TimeTrial? TimeTrial { get; set; } public User? User { get; set; } } public class Car { public int Id { get; set; } public string CarId { get; set; } = string.Empty; // Unique identifier like "porsche_911_gt3" public string Name { get; set; } = string.Empty; public string Manufacturer { get; set; } = string.Empty; public string ClassType { get; set; } = string.Empty; // C, B, A, S, R public int BasePerformanceRating { get; set; } // Base PR before upgrades public int CashPrice { get; set; } public int GoldPrice { get; set; } public bool Available { get; set; } = true; public int Year { get; set; } public string? Description { get; set; } // Custom content fields public bool IsCustom { get; set; } public string? CustomAuthor { get; set; } public string? CustomVersion { get; set; } public DateTime? CreatedAt { get; set; } } public class OwnedCar { public int Id { get; set; } public int UserId { get; set; } public string CarId { get; set; } = string.Empty; public string CarName { get; set; } = string.Empty; public string Manufacturer { get; set; } = string.Empty; public string ClassType { get; set; } = string.Empty; public int PerformanceRating { get; set; } // Current PR with upgrades public int UpgradeLevel { get; set; } // 0-5 public string PurchasedUpgrades { get; set; } = string.Empty; // Comma-separated list public DateTime PurchasedAt { get; set; } = DateTime.UtcNow; } public class CarUpgrade { public int Id { get; set; } public string CarId { get; set; } = string.Empty; public string UpgradeType { get; set; } = string.Empty; // engine, tires, suspension, brakes, drivetrain public int Level { get; set; } // 1-5 public int CashCost { get; set; } public int PerformanceIncrease { get; set; } } public class CareerProgress { public int Id { get; set; } public int UserId { get; set; } public string SeriesName { get; set; } = string.Empty; // e.g., "Road Collection", "Endurance Legends" public string EventName { get; set; } = string.Empty; // e.g., "Brands Hatch GP Circuit" public bool Completed { get; set; } public int StarsEarned { get; set; } // 0-3 public double BestTime { get; set; } public DateTime? CompletedAt { get; set; } } public class GameAsset { public int Id { get; set; } // Asset identification public string AssetId { get; set; } = string.Empty; public string AssetType { get; set; } = string.Empty; // car, track, texture, audio, etc. public string FileName { get; set; } = string.Empty; public string ContentType { get; set; } = "application/octet-stream"; // EA CDN info public string? OriginalUrl { get; set; } public string? EaCdnPath { get; set; } // Local storage public string? LocalPath { get; set; } public long FileSize { get; set; } public string? FileSha256 { get; set; } public string? Version { get; set; } // Metadata public DateTime DownloadedAt { get; set; } = DateTime.UtcNow; public DateTime UploadedAt { get; set; } = DateTime.UtcNow; public DateTime LastAccessedAt { get; set; } = DateTime.UtcNow; public int AccessCount { get; set; } = 0; public bool IsAvailable { get; set; } = true; public bool IsRequired { get; set; } = false; // Game-specific (optional) public string? CarId { get; set; } public string? TrackId { get; set; } public string Category { get; set; } = "misc"; // models, textures, audio, etc. public long? CompressedSize { get; set; } public string? Md5Hash { get; set; } public string? Description { get; set; } // Custom content support public bool IsCustomContent { get; set; } public string? CustomAuthor { get; set; } } public class PlayerSave { public int Id { get; set; } public string SynergyId { get; set; } = string.Empty; public string SaveDataJson { get; set; } = "{}"; public long Version { get; set; } = 1; public DateTime LastModified { get; set; } = DateTime.UtcNow; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } public class LeaderboardEntry { public int Id { get; set; } public string SynergyId { get; set; } = string.Empty; public string PlayerName { get; set; } = string.Empty; public string RecordType { get; set; } = string.Empty; // "TimeTrial", "Career", "Multiplayer" public string RecordCategory { get; set; } = string.Empty; public string? TrackName { get; set; } public string? CarName { get; set; } public double TimeSeconds { get; set; } public DateTime SubmittedAt { get; set; } } public class PersonalRecord { public int Id { get; set; } public string SynergyId { get; set; } = string.Empty; public string RecordType { get; set; } = string.Empty; public string RecordCategory { get; set; } = string.Empty; public string? TrackName { get; set; } public string? CarName { get; set; } public double BestTimeSeconds { get; set; } public DateTime AchievedAt { get; set; } public DateTime? PreviousBestTime { get; set; } public double? ImprovementSeconds { get; set; } public int TotalAttempts { get; set; } } // Mod Pack entity - bundles of custom content public class ModPack { public int Id { get; set; } public string PackId { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Author { get; set; } = string.Empty; public string? Description { get; set; } public string Version { get; set; } = "1.0"; // Comma-separated IDs public string? CarIds { get; set; } public string? TrackIds { get; set; } // Statistics public int DownloadCount { get; set; } public double Rating { get; set; } public DateTime CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } } // Career Events entity public class Event { public int Id { get; set; } public string EventCode { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string SeriesName { get; set; } = string.Empty; public int SeriesOrder { get; set; } public int EventOrder { get; set; } public string Track { get; set; } = string.Empty; public string EventType { get; set; } = "race"; // race, duel, elimination, etc public int Laps { get; set; } public int RequiredPR { get; set; } public string? RequiredCarClass { get; set; } public double? TargetTime { get; set; } public int GoldReward { get; set; } public int CashReward { get; set; } public int XPReward { get; set; } public bool Active { get; set; } = true; } // Tracks player's completion of events public class EventCompletion { public int Id { get; set; } public int UserId { get; set; } public int EventId { get; set; } public double BestTime { get; set; } public int CompletionCount { get; set; } public DateTime FirstCompletedAt { get; set; } public DateTime LastCompletedAt { get; set; } // Navigation properties public User? User { get; set; } public Event? Event { get; set; } } // Tracks active event attempts public class EventAttempt { public int Id { get; set; } public int UserId { get; set; } public int EventId { get; set; } public DateTime StartedAt { get; set; } public bool Completed { get; set; } public DateTime? CompletedAt { get; set; } public double? TimeSeconds { get; set; } // Navigation properties public User? User { get; set; } public Event? Event { get; set; } } // In-game notifications public class Notification { public int Id { get; set; } public int UserId { get; set; } public string Type { get; set; } = string.Empty; // "reward", "event", "system", "friend" public string Title { get; set; } = string.Empty; public string Message { get; set; } = string.Empty; public bool IsRead { get; set; } = false; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? ExpiresAt { get; set; } // Navigation property public User? User { get; set; } } // Friend relationships public class Friend { public int Id { get; set; } public int User1Id { get; set; } public int User2Id { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Navigation properties public User? User1 { get; set; } public User? User2 { get; set; } } // Friend invitations (pending requests) public class FriendInvitation { public int Id { get; set; } public int SenderId { get; set; } public int ReceiverId { get; set; } public string Status { get; set; } = "pending"; // "pending", "accepted", "declined", "expired" public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? RespondedAt { get; set; } public DateTime ExpiresAt { get; set; } = DateTime.UtcNow.AddDays(7); // Navigation properties public User? Sender { get; set; } public User? Receiver { get; set; } } // Gifts between friends public class Gift { public int Id { get; set; } public int SenderId { get; set; } public int ReceiverId { get; set; } public string GiftType { get; set; } = string.Empty; // "gold", "cash", "boost" public int Amount { get; set; } public string? Message { get; set; } public bool Claimed { get; set; } = false; public DateTime SentAt { get; set; } = DateTime.UtcNow; public DateTime? ClaimedAt { get; set; } public DateTime ExpiresAt { get; set; } = DateTime.UtcNow.AddDays(7); // Navigation properties public User? Sender { get; set; } public User? Receiver { get; set; } } // Clubs/Teams public class Club { public int Id { get; set; } public string Name { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; public string Tag { get; set; } = string.Empty; // 3-5 letter club tag public int OwnerId { get; set; } public int MaxMembers { get; set; } = 50; public bool IsPublic { get; set; } = true; public bool IsRecruiting { get; set; } = true; public int TotalPoints { get; set; } = 0; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Navigation properties public User? Owner { get; set; } public ICollection Members { get; set; } = new List(); } // Club memberships public class ClubMember { public int Id { get; set; } public int ClubId { get; set; } public int UserId { get; set; } public string Role { get; set; } = "member"; // "owner", "admin", "member" public int ContributedPoints { get; set; } = 0; public DateTime JoinedAt { get; set; } = DateTime.UtcNow; // Navigation properties public Club? Club { get; set; } public User? User { get; set; } } // ===== MULTIPLAYER SYSTEM ENTITIES ===== // Matchmaking queue entries public class MatchmakingQueue { public int Id { get; set; } public int UserId { get; set; } public string CarClass { get; set; } = string.Empty; public string Track { get; set; } = string.Empty; public string GameMode { get; set; } = string.Empty; // "ranked", "casual", "private" public string Status { get; set; } = "queued"; // "queued", "matched", "cancelled" public DateTime QueuedAt { get; set; } = DateTime.UtcNow; public DateTime? MatchedAt { get; set; } public int? SessionId { get; set; } // Navigation properties public User? User { get; set; } public RaceSession? Session { get; set; } } // Race sessions (lobbies) public class RaceSession { public int Id { get; set; } public string SessionCode { get; set; } = string.Empty; // 6-digit join code public string Track { get; set; } = string.Empty; public string CarClass { get; set; } = string.Empty; public int HostUserId { get; set; } public int MaxPlayers { get; set; } = 8; public string Status { get; set; } = "lobby"; // "lobby", "countdown", "racing", "finished" public bool IsPrivate { get; set; } = false; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? StartedAt { get; set; } public DateTime? FinishedAt { get; set; } // Navigation properties public User? Host { get; set; } public ICollection Participants { get; set; } = new List(); } // Race session participants public class RaceParticipant { public int Id { get; set; } public int SessionId { get; set; } public int UserId { get; set; } public string CarId { get; set; } = string.Empty; public bool IsReady { get; set; } = false; public int? FinishPosition { get; set; } public double? RaceTime { get; set; } public int? RewardGold { get; set; } public int? RewardCash { get; set; } public int? RewardXP { get; set; } public DateTime JoinedAt { get; set; } = DateTime.UtcNow; // Navigation properties public RaceSession? Session { get; set; } public User? User { get; set; } } // Ghost race data public class GhostData { public int Id { get; set; } public int UserId { get; set; } public string Track { get; set; } = string.Empty; public string CarId { get; set; } = string.Empty; public double RaceTime { get; set; } public string TelemetryData { get; set; } = string.Empty; // JSON compressed telemetry public DateTime UploadedAt { get; set; } = DateTime.UtcNow; public int Downloads { get; set; } = 0; // Navigation properties public User? User { get; set; } } // Competitive ratings (ranked mode) public class CompetitiveRating { public int Id { get; set; } public int UserId { get; set; } public int Rating { get; set; } = 1000; // ELO-style rating public int Wins { get; set; } = 0; public int Losses { get; set; } = 0; public int Draws { get; set; } = 0; public string Division { get; set; } = "Bronze"; // Bronze, Silver, Gold, Platinum, Diamond public int DivisionRank { get; set; } = 0; public DateTime LastMatchAt { get; set; } = DateTime.UtcNow; // Navigation properties public User? User { get; set; } }