From 0d6aaa1d9d1d5346331184be67ced0bc83948bdf Mon Sep 17 00:00:00 2001 From: RaidMax Date: Mon, 1 May 2023 22:33:47 -0500 Subject: [PATCH] add initial public zombie stats models, migrations, and events --- Data/Context/DatabaseContext.cs | 20 +- ...02032705_AddZombieStatsInitial.Designer.cs | 1909 +++++++++++++++++ .../20230502032705_AddZombieStatsInitial.cs | 230 ++ .../SqliteDatabaseContextModelSnapshot.cs | 270 +++ Data/Models/Client/EFClient.cs | 6 + .../Zombie/ZombieAggregateClientStat.cs | 27 + Data/Models/Zombie/ZombieClientStat.cs | 34 + Data/Models/Zombie/ZombieMatch.cs | 28 + Data/Models/Zombie/ZombieMatchClientStat.cs | 6 + Data/Models/Zombie/ZombieRoundClientStat.cs | 13 + .../Zombie/PlayerConsumedPerkGameEvent.cs | 9 + .../Zombie/PlayerDamageGameEvent.cs | 6 + .../Zombie/PlayerDownedGameEvent.cs | 6 + .../Zombie/PlayerGrabbedPowerupameEvent.cs | 9 + .../Zombie/PlayerKilledGameEvent.cs | 9 + .../Zombie/PlayerRevivedGameEvent.cs | 9 + .../Zombie/PlayerRoundDataGameEvent.cs | 8 + .../Zombie/RoundCompleteGameEvent.cs | 6 + .../Zombie/ZombieDamageGameEvent.cs | 6 + .../Zombie/ZombieKilledGameEvent.cs | 9 + 20 files changed, 2616 insertions(+), 4 deletions(-) create mode 100644 Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.Designer.cs create mode 100644 Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.cs create mode 100644 Data/Models/Zombie/ZombieAggregateClientStat.cs create mode 100644 Data/Models/Zombie/ZombieClientStat.cs create mode 100644 Data/Models/Zombie/ZombieMatch.cs create mode 100644 Data/Models/Zombie/ZombieMatchClientStat.cs create mode 100644 Data/Models/Zombie/ZombieRoundClientStat.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerConsumedPerkGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDamageGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDownedGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerGrabbedPowerupameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerKilledGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRevivedGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRoundDataGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/RoundCompleteGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieDamageGameEvent.cs create mode 100644 SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieKilledGameEvent.cs diff --git a/Data/Context/DatabaseContext.cs b/Data/Context/DatabaseContext.cs index 5eee90664..f1f9bb544 100644 --- a/Data/Context/DatabaseContext.cs +++ b/Data/Context/DatabaseContext.cs @@ -9,6 +9,7 @@ using Data.Models.Client.Stats; using Data.Models.Client.Stats.Reference; using Data.Models.Misc; using Data.Models.Server; +using Data.Models.Zombie; namespace Data.Context { @@ -47,6 +48,15 @@ namespace Data.Context public DbSet ServerSnapshots { get;set; } public DbSet ConnectionHistory { get; set; } + #endregion + + #region Zombie + + public DbSet ZombieMatches { get; set; } + public DbSet ZombieMatchClientStats { get; set; } + public DbSet ZombieRoundClientStats { get; set; } + public DbSet ZombieClientStatAggregates { get; set; } + #endregion private void SetAuditColumns() @@ -62,10 +72,6 @@ namespace Data.Context } } - public DatabaseContext(DbContextOptions options) : base(options) - { - } - protected DatabaseContext(DbContextOptions options) : base(options) { } @@ -161,6 +167,12 @@ namespace Data.Context modelBuilder.Entity().ToTable("EFPenaltyIdentifiers"); modelBuilder.Entity().ToTable(nameof(EFServerSnapshot)); modelBuilder.Entity().ToTable(nameof(EFClientConnectionHistory)); + + modelBuilder.Entity(typeof(ZombieMatch)).ToTable($"EF{nameof(ZombieMatch)}"); + modelBuilder.Entity(typeof(ZombieMatchClientStat)).ToTable($"EF{nameof(ZombieMatchClientStat)}"); + modelBuilder.Entity(typeof(ZombieRoundClientStat)).ToTable($"EF{nameof(ZombieRoundClientStat)}"); + modelBuilder.Entity(typeof(ZombieAggregateClientStat)).ToTable($"EF{nameof(ZombieAggregateClientStat)}"); + modelBuilder.Entity(typeof(ZombieClientStat)).ToTable($"EF{nameof(ZombieClientStat)}"); Models.Configuration.StatsModelConfiguration.Configure(modelBuilder); diff --git a/Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.Designer.cs b/Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.Designer.cs new file mode 100644 index 000000000..13109d2fb --- /dev/null +++ b/Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.Designer.cs @@ -0,0 +1,1909 @@ +// +using System; +using Data.MigrationContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Data.Migrations.Sqlite +{ + [DbContext(typeof(SqliteDatabaseContext))] + [Migration("20230502032705_AddZombieStatsInitial")] + partial class AddZombieStatsInitial + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.Property("ACSnapshotVector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("SnapshotId") + .HasColumnType("INTEGER"); + + b.Property("Vector3Id") + .HasColumnType("INTEGER"); + + b.HasKey("ACSnapshotVector3Id"); + + b.HasIndex("SnapshotId"); + + b.HasIndex("Vector3Id"); + + b.ToTable("EFACSnapshotVector3", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Property("ClientId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AliasLinkId") + .HasColumnType("INTEGER"); + + b.Property("Connections") + .HasColumnType("INTEGER"); + + b.Property("CurrentAliasId") + .HasColumnType("INTEGER"); + + b.Property("FirstConnection") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("LastConnection") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Masked") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("PasswordSalt") + .HasColumnType("TEXT"); + + b.Property("TotalConnectionTime") + .HasColumnType("INTEGER"); + + b.HasKey("ClientId"); + + b.HasAlternateKey("NetworkId", "GameName"); + + b.HasIndex("AliasLinkId"); + + b.HasIndex("CurrentAliasId"); + + b.HasIndex("LastConnection"); + + b.HasIndex("NetworkId"); + + b.ToTable("EFClients", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientConnectionHistory", b => + { + b.Property("ClientConnectionId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ConnectionType") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("ClientConnectionId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CreatedDateTime"); + + b.HasIndex("ServerId"); + + b.ToTable("EFClientConnectionHistory", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.Property("KillId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AttackerId") + .HasColumnType("INTEGER"); + + b.Property("Damage") + .HasColumnType("INTEGER"); + + b.Property("DeathOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("DeathType") + .HasColumnType("INTEGER"); + + b.Property("Fraction") + .HasColumnType("REAL"); + + b.Property("HitLoc") + .HasColumnType("INTEGER"); + + b.Property("IsKill") + .HasColumnType("INTEGER"); + + b.Property("KillOriginVector3Id") + .HasColumnType("INTEGER"); + + b.Property("Map") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("VictimId") + .HasColumnType("INTEGER"); + + b.Property("ViewAnglesVector3Id") + .HasColumnType("INTEGER"); + + b.Property("VisibilityPercentage") + .HasColumnType("REAL"); + + b.Property("Weapon") + .HasColumnType("INTEGER"); + + b.Property("WeaponReference") + .HasColumnType("TEXT"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("KillId"); + + b.HasIndex("AttackerId"); + + b.HasIndex("DeathOriginVector3Id"); + + b.HasIndex("KillOriginVector3Id"); + + b.HasIndex("ServerId"); + + b.HasIndex("VictimId"); + + b.HasIndex("ViewAnglesVector3Id"); + + b.ToTable("EFClientKills", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.Property("MessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("SentIngame") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TimeSent") + .HasColumnType("TEXT"); + + b.HasKey("MessageId"); + + b.HasIndex("ClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("TimeSent"); + + b.ToTable("EFClientMessages", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CurrentSessionLength") + .HasColumnType("INTEGER"); + + b.Property("CurrentStrain") + .HasColumnType("REAL"); + + b.Property("CurrentViewAngleId") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Distance") + .HasColumnType("REAL"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("HitDestinationId") + .HasColumnType("INTEGER"); + + b.Property("HitLocation") + .HasColumnType("INTEGER"); + + b.Property("HitLocationReference") + .HasColumnType("TEXT"); + + b.Property("HitOriginId") + .HasColumnType("INTEGER"); + + b.Property("HitType") + .HasColumnType("INTEGER"); + + b.Property("Hits") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("LastStrainAngleId") + .HasColumnType("INTEGER"); + + b.Property("RecoilOffset") + .HasColumnType("REAL"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("SessionAngleOffset") + .HasColumnType("REAL"); + + b.Property("SessionAverageSnapValue") + .HasColumnType("REAL"); + + b.Property("SessionSPM") + .HasColumnType("REAL"); + + b.Property("SessionScore") + .HasColumnType("INTEGER"); + + b.Property("SessionSnapHits") + .HasColumnType("INTEGER"); + + b.Property("StrainAngleBetween") + .HasColumnType("REAL"); + + b.Property("TimeSinceLastEvent") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.Property("WeaponReference") + .HasColumnType("TEXT"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("SnapshotId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CurrentViewAngleId"); + + b.HasIndex("HitDestinationId"); + + b.HasIndex("HitOriginId"); + + b.HasIndex("LastStrainAngleId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFACSnapshot", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.Property("ClientHitStatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("DamageInflicted") + .HasColumnType("INTEGER"); + + b.Property("DamageReceived") + .HasColumnType("INTEGER"); + + b.Property("DeathCount") + .HasColumnType("INTEGER"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitLocationId") + .HasColumnType("INTEGER"); + + b.Property("KillCount") + .HasColumnType("INTEGER"); + + b.Property("MeansOfDeathId") + .HasColumnType("INTEGER"); + + b.Property("ReceivedHitCount") + .HasColumnType("INTEGER"); + + b.Property("Score") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("SuicideCount") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.Property("UsageSeconds") + .HasColumnType("INTEGER"); + + b.Property("WeaponAttachmentComboId") + .HasColumnType("INTEGER"); + + b.Property("WeaponId") + .HasColumnType("INTEGER"); + + b.HasKey("ClientHitStatisticId"); + + b.HasIndex("ClientId"); + + b.HasIndex("HitLocationId"); + + b.HasIndex("MeansOfDeathId"); + + b.HasIndex("ServerId"); + + b.HasIndex("WeaponAttachmentComboId"); + + b.HasIndex("WeaponId"); + + b.ToTable("EFClientHitStatistics", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.Property("ClientRankingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("PerformanceMetric") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.Property("ZScore") + .HasColumnType("REAL"); + + b.HasKey("ClientRankingHistoryId"); + + b.HasIndex("ClientId"); + + b.HasIndex("CreatedDateTime"); + + b.HasIndex("Ranking"); + + b.HasIndex("ServerId"); + + b.HasIndex("UpdatedDateTime"); + + b.HasIndex("ZScore"); + + b.ToTable("EFClientRankingHistory", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.Property("RatingHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.HasKey("RatingHistoryId"); + + b.HasIndex("ClientId"); + + b.ToTable("EFClientRatingHistory", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AverageSnapValue") + .HasColumnType("REAL"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("EloRating") + .HasColumnType("REAL"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MaxStrain") + .HasColumnType("REAL"); + + b.Property("RollingWeightedKDR") + .HasColumnType("REAL"); + + b.Property("SPM") + .HasColumnType("REAL"); + + b.Property("Skill") + .HasColumnType("REAL"); + + b.Property("SnapHitCount") + .HasColumnType("INTEGER"); + + b.Property("TimePlayed") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("ZScore") + .HasColumnType("REAL"); + + b.HasKey("ClientId", "ServerId"); + + b.HasIndex("ServerId"); + + b.HasIndex("ZScore"); + + b.HasIndex("ClientId", "TimePlayed", "ZScore"); + + b.ToTable("EFClientStatistics", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.Property("HitLocationCountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EFClientStatisticsClientId") + .HasColumnType("INTEGER") + .HasColumnName("EFClientStatisticsClientId"); + + b.Property("EFClientStatisticsServerId") + .HasColumnType("INTEGER") + .HasColumnName("EFClientStatisticsServerId"); + + b.Property("HitCount") + .HasColumnType("INTEGER"); + + b.Property("HitOffsetAverage") + .HasColumnType("REAL"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("MaxAngleDistance") + .HasColumnType("REAL"); + + b.HasKey("HitLocationCountId"); + + b.HasIndex("EFClientStatisticsServerId"); + + b.HasIndex("EFClientStatisticsClientId", "EFClientStatisticsServerId"); + + b.ToTable("EFHitLocationCounts", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.Property("RatingId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ActivityAmount") + .HasColumnType("INTEGER"); + + b.Property("Newest") + .HasColumnType("INTEGER"); + + b.Property("Performance") + .HasColumnType("REAL"); + + b.Property("Ranking") + .HasColumnType("INTEGER"); + + b.Property("RatingHistoryId") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("RatingId"); + + b.HasIndex("RatingHistoryId"); + + b.HasIndex("ServerId"); + + b.HasIndex("Performance", "Ranking", "When"); + + b.HasIndex("When", "ServerId", "Performance", "ActivityAmount"); + + b.ToTable("EFRating", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFHitLocation", b => + { + b.Property("HitLocationId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("HitLocationId"); + + b.HasIndex("Name"); + + b.ToTable("EFHitLocations", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMap", b => + { + b.Property("MapId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MapId"); + + b.ToTable("EFMaps", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFMeansOfDeath", b => + { + b.Property("MeansOfDeathId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("MeansOfDeathId"); + + b.ToTable("EFMeansOfDeath", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeapon", b => + { + b.Property("WeaponId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponId"); + + b.HasIndex("Name"); + + b.ToTable("EFWeapons", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachment", b => + { + b.Property("WeaponAttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentId"); + + b.ToTable("EFWeaponAttachments", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.Property("WeaponAttachmentComboId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Attachment1Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment2Id") + .HasColumnType("INTEGER"); + + b.Property("Attachment3Id") + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("WeaponAttachmentComboId"); + + b.HasIndex("Attachment1Id"); + + b.HasIndex("Attachment2Id"); + + b.HasIndex("Attachment3Id"); + + b.ToTable("EFWeaponAttachmentCombos", (string)null); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.Property("AliasId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IPAddress") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(24) + .HasColumnType("TEXT"); + + b.Property("SearchableIPAddress") + .ValueGeneratedOnAddOrUpdate() + .HasMaxLength(255) + .HasColumnType("TEXT") + .HasComputedColumnSql("((IPAddress & 255) || '.' || ((IPAddress >> 8) & 255)) || '.' || ((IPAddress >> 16) & 255) || '.' || ((IPAddress >> 24) & 255)", true); + + b.Property("SearchableName") + .HasMaxLength(24) + .HasColumnType("TEXT"); + + b.HasKey("AliasId"); + + b.HasIndex("IPAddress"); + + b.HasIndex("LinkId"); + + b.HasIndex("Name"); + + b.HasIndex("SearchableIPAddress"); + + b.HasIndex("SearchableName"); + + b.HasIndex("Name", "IPAddress"); + + b.ToTable("EFAlias", (string)null); + }); + + modelBuilder.Entity("Data.Models.EFAliasLink", b => + { + b.Property("AliasLinkId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.HasKey("AliasLinkId"); + + b.ToTable("EFAliasLinks", (string)null); + }); + + modelBuilder.Entity("Data.Models.EFChangeHistory", b => + { + b.Property("ChangeHistoryId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("CurrentValue") + .HasColumnType("TEXT"); + + b.Property("ImpersonationEntityId") + .HasColumnType("INTEGER"); + + b.Property("OriginEntityId") + .HasColumnType("INTEGER"); + + b.Property("PreviousValue") + .HasColumnType("TEXT"); + + b.Property("TargetEntityId") + .HasColumnType("INTEGER"); + + b.Property("TimeChanged") + .HasColumnType("TEXT"); + + b.Property("TypeOfChange") + .HasColumnType("INTEGER"); + + b.HasKey("ChangeHistoryId"); + + b.ToTable("EFChangeHistory"); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.Property("MetaId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("Extra") + .HasColumnType("TEXT"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("LinkedMetaId") + .HasColumnType("INTEGER"); + + b.Property("Updated") + .HasColumnType("TEXT"); + + b.Property("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MetaId"); + + b.HasIndex("ClientId"); + + b.HasIndex("Key"); + + b.HasIndex("LinkedMetaId"); + + b.ToTable("EFMeta"); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.Property("PenaltyId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("AutomatedOffense") + .HasColumnType("TEXT"); + + b.Property("Expires") + .HasColumnType("TEXT"); + + b.Property("IsEvadedOffense") + .HasColumnType("INTEGER"); + + b.Property("LinkId") + .HasColumnType("INTEGER"); + + b.Property("OffenderId") + .HasColumnType("INTEGER"); + + b.Property("Offense") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PunisherId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyId"); + + b.HasIndex("LinkId"); + + b.HasIndex("OffenderId"); + + b.HasIndex("PunisherId"); + + b.ToTable("EFPenalties", (string)null); + }); + + modelBuilder.Entity("Data.Models.EFPenaltyIdentifier", b => + { + b.Property("PenaltyIdentifierId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("IPv4Address") + .HasColumnType("INTEGER"); + + b.Property("NetworkId") + .HasColumnType("INTEGER"); + + b.Property("PenaltyId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("PenaltyIdentifierId"); + + b.HasIndex("IPv4Address"); + + b.HasIndex("NetworkId"); + + b.HasIndex("PenaltyId"); + + b.ToTable("EFPenaltyIdentifiers", (string)null); + }); + + modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b => + { + b.Property("InboxMessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDateTime") + .HasColumnType("TEXT"); + + b.Property("DestinationClientId") + .HasColumnType("INTEGER"); + + b.Property("IsDelivered") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("SourceClientId") + .HasColumnType("INTEGER"); + + b.Property("UpdatedDateTime") + .HasColumnType("TEXT"); + + b.HasKey("InboxMessageId"); + + b.HasIndex("DestinationClientId"); + + b.HasIndex("ServerId"); + + b.HasIndex("SourceClientId"); + + b.ToTable("InboxMessages"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServer", b => + { + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("EndPoint") + .HasColumnType("TEXT"); + + b.Property("GameName") + .HasColumnType("INTEGER"); + + b.Property("HostName") + .HasColumnType("TEXT"); + + b.Property("IsPasswordProtected") + .HasColumnType("INTEGER"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.HasKey("ServerId"); + + b.ToTable("EFServers", (string)null); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerSnapshot", b => + { + b.Property("ServerSnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("CapturedAt") + .HasColumnType("TEXT"); + + b.Property("ClientCount") + .HasColumnType("INTEGER"); + + b.Property("ConnectionInterrupted") + .HasColumnType("INTEGER"); + + b.Property("MapId") + .HasColumnType("INTEGER"); + + b.Property("PeriodBlock") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.HasKey("ServerSnapshotId"); + + b.HasIndex("MapId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerSnapshot", (string)null); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.Property("StatisticId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("TotalKills") + .HasColumnType("INTEGER"); + + b.Property("TotalPlayTime") + .HasColumnType("INTEGER"); + + b.HasKey("StatisticId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFServerStatistics", (string)null); + }); + + modelBuilder.Entity("Data.Models.Vector3", b => + { + b.Property("Vector3Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("X") + .HasColumnType("REAL"); + + b.Property("Y") + .HasColumnType("REAL"); + + b.Property("Z") + .HasColumnType("REAL"); + + b.HasKey("Vector3Id"); + + b.ToTable("Vector3", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieClientStat", b => + { + b.Property("ZombieClientStatId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("DamageDealt") + .HasColumnType("INTEGER"); + + b.Property("DamageReceived") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Downs") + .HasColumnType("INTEGER"); + + b.Property("Headshots") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MatchId") + .HasColumnType("INTEGER"); + + b.Property("Melees") + .HasColumnType("INTEGER"); + + b.Property("PerksConsumed") + .HasColumnType("INTEGER"); + + b.Property("PointsEarned") + .HasColumnType("INTEGER"); + + b.Property("PointsSpent") + .HasColumnType("INTEGER"); + + b.Property("PowerupsGrabbed") + .HasColumnType("INTEGER"); + + b.Property("Revives") + .HasColumnType("INTEGER"); + + b.HasKey("ZombieClientStatId"); + + b.HasIndex("ClientId"); + + b.HasIndex("MatchId"); + + b.ToTable("EFZombieClientStat", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatch", b => + { + b.Property("ZombieMatchId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.Property("MapId") + .HasColumnType("INTEGER"); + + b.Property("MatchEndDate") + .HasColumnType("TEXT"); + + b.Property("MatchStartDate") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.HasKey("ZombieMatchId"); + + b.HasIndex("EFClientClientId"); + + b.HasIndex("MapId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFZombieMatch", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieAggregateClientStat", b => + { + b.HasBaseType("Data.Models.Zombie.ZombieClientStat"); + + b.Property("AlivePercentage") + .HasColumnType("REAL"); + + b.Property("AverageDowns") + .HasColumnType("REAL"); + + b.Property("AverageKillsPerDown") + .HasColumnType("REAL"); + + b.Property("AverageMelees") + .HasColumnType("REAL"); + + b.Property("AveragePoints") + .HasColumnType("REAL"); + + b.Property("AverageRevives") + .HasColumnType("REAL"); + + b.Property("AverageRoundReached") + .HasColumnType("REAL"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.Property("HeadshotPercentage") + .HasColumnType("REAL"); + + b.Property("HighestRound") + .HasColumnType("INTEGER"); + + b.Property("RankingMetric") + .HasColumnType("REAL"); + + b.Property("TotalMatchesPlayed") + .HasColumnType("INTEGER"); + + b.Property("TotalRoundsPlayed") + .HasColumnType("INTEGER"); + + b.HasIndex("EFClientClientId"); + + b.ToTable("EFZombieAggregateClientStat", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatchClientStat", b => + { + b.HasBaseType("Data.Models.Zombie.ZombieClientStat"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.HasIndex("EFClientClientId"); + + b.ToTable("EFZombieMatchClientStat", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieRoundClientStat", b => + { + b.HasBaseType("Data.Models.Zombie.ZombieClientStat"); + + b.Property("Duration") + .HasColumnType("TEXT"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.Property("EndTime") + .HasColumnType("TEXT"); + + b.Property("Points") + .HasColumnType("INTEGER"); + + b.Property("RoundNumber") + .HasColumnType("INTEGER"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("TimeAlive") + .HasColumnType("TEXT"); + + b.HasIndex("EFClientClientId"); + + b.ToTable("EFZombieRoundClientStat", (string)null); + }); + + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => + { + b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") + .WithMany("PredictedViewAngles") + .HasForeignKey("SnapshotId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "Vector") + .WithMany() + .HasForeignKey("Vector3Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Snapshot"); + + b.Navigation("Vector"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.HasOne("Data.Models.EFAliasLink", "AliasLink") + .WithMany() + .HasForeignKey("AliasLinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.EFAlias", "CurrentAlias") + .WithMany() + .HasForeignKey("CurrentAliasId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AliasLink"); + + b.Navigation("CurrentAlias"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientConnectionHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientKill", b => + { + b.HasOne("Data.Models.Client.EFClient", "Attacker") + .WithMany() + .HasForeignKey("AttackerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "DeathOrigin") + .WithMany() + .HasForeignKey("DeathOriginVector3Id"); + + b.HasOne("Data.Models.Vector3", "KillOrigin") + .WithMany() + .HasForeignKey("KillOriginVector3Id"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Victim") + .WithMany() + .HasForeignKey("VictimId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "ViewAngles") + .WithMany() + .HasForeignKey("ViewAnglesVector3Id"); + + b.Navigation("Attacker"); + + b.Navigation("DeathOrigin"); + + b.Navigation("KillOrigin"); + + b.Navigation("Server"); + + b.Navigation("Victim"); + + b.Navigation("ViewAngles"); + }); + + modelBuilder.Entity("Data.Models.Client.EFClientMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "CurrentViewAngle") + .WithMany() + .HasForeignKey("CurrentViewAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitDestination") + .WithMany() + .HasForeignKey("HitDestinationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "HitOrigin") + .WithMany() + .HasForeignKey("HitOriginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Vector3", "LastStrainAngle") + .WithMany() + .HasForeignKey("LastStrainAngleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.Navigation("Client"); + + b.Navigation("CurrentViewAngle"); + + b.Navigation("HitDestination"); + + b.Navigation("HitOrigin"); + + b.Navigation("LastStrainAngle"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientHitStatistic", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFHitLocation", "HitLocation") + .WithMany() + .HasForeignKey("HitLocationId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMeansOfDeath", "MeansOfDeath") + .WithMany() + .HasForeignKey("MeansOfDeathId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", "WeaponAttachmentCombo") + .WithMany() + .HasForeignKey("WeaponAttachmentComboId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeapon", "Weapon") + .WithMany() + .HasForeignKey("WeaponId"); + + b.Navigation("Client"); + + b.Navigation("HitLocation"); + + b.Navigation("MeansOfDeath"); + + b.Navigation("Server"); + + b.Navigation("Weapon"); + + b.Navigation("WeaponAttachmentCombo"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRankingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.Navigation("Client"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFHitLocationCount", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany() + .HasForeignKey("EFClientStatisticsClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.EFClientStatistics", null) + .WithMany("HitLocations") + .HasForeignKey("EFClientStatisticsClientId", "EFClientStatisticsServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Client"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFRating", b => + { + b.HasOne("Data.Models.Client.Stats.EFClientRatingHistory", "RatingHistory") + .WithMany("Ratings") + .HasForeignKey("RatingHistoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.Navigation("RatingHistory"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.Reference.EFWeaponAttachmentCombo", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment1") + .WithMany() + .HasForeignKey("Attachment1Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment2") + .WithMany() + .HasForeignKey("Attachment2Id"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFWeaponAttachment", "Attachment3") + .WithMany() + .HasForeignKey("Attachment3Id"); + + b.Navigation("Attachment1"); + + b.Navigation("Attachment2"); + + b.Navigation("Attachment3"); + }); + + modelBuilder.Entity("Data.Models.EFAlias", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("Children") + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Link"); + }); + + modelBuilder.Entity("Data.Models.EFMeta", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany("Meta") + .HasForeignKey("ClientId"); + + b.HasOne("Data.Models.EFMeta", "LinkedMeta") + .WithMany() + .HasForeignKey("LinkedMetaId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Client"); + + b.Navigation("LinkedMeta"); + }); + + modelBuilder.Entity("Data.Models.EFPenalty", b => + { + b.HasOne("Data.Models.EFAliasLink", "Link") + .WithMany("ReceivedPenalties") + .HasForeignKey("LinkId"); + + b.HasOne("Data.Models.Client.EFClient", "Offender") + .WithMany("ReceivedPenalties") + .HasForeignKey("OffenderId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Data.Models.Client.EFClient", "Punisher") + .WithMany("AdministeredPenalties") + .HasForeignKey("PunisherId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Link"); + + b.Navigation("Offender"); + + b.Navigation("Punisher"); + }); + + modelBuilder.Entity("Data.Models.EFPenaltyIdentifier", b => + { + b.HasOne("Data.Models.EFPenalty", "Penalty") + .WithMany() + .HasForeignKey("PenaltyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Penalty"); + }); + + modelBuilder.Entity("Data.Models.Misc.EFInboxMessage", b => + { + b.HasOne("Data.Models.Client.EFClient", "DestinationClient") + .WithMany() + .HasForeignKey("DestinationClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.HasOne("Data.Models.Client.EFClient", "SourceClient") + .WithMany() + .HasForeignKey("SourceClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DestinationClient"); + + b.Navigation("Server"); + + b.Navigation("SourceClient"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerSnapshot", b => + { + b.HasOne("Data.Models.Client.Stats.Reference.EFMap", "Map") + .WithMany() + .HasForeignKey("MapId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Map"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Server.EFServerStatistics", b => + { + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany("ZombieClientStats") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Zombie.ZombieMatch", "Match") + .WithMany("ClientStats") + .HasForeignKey("MatchId"); + + b.Navigation("Client"); + + b.Navigation("Match"); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatch", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieMatches") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMap", "Map") + .WithMany() + .HasForeignKey("MapId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.Navigation("Map"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieAggregateClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieAggregateClientStats") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Zombie.ZombieClientStat", null) + .WithOne() + .HasForeignKey("Data.Models.Zombie.ZombieAggregateClientStat", "ZombieClientStatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatchClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieMatchClientStats") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Zombie.ZombieClientStat", null) + .WithOne() + .HasForeignKey("Data.Models.Zombie.ZombieMatchClientStat", "ZombieClientStatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieRoundClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieRoundClientStats") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Zombie.ZombieClientStat", null) + .WithOne() + .HasForeignKey("Data.Models.Zombie.ZombieRoundClientStat", "ZombieClientStatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Client.EFClient", b => + { + b.Navigation("AdministeredPenalties"); + + b.Navigation("Meta"); + + b.Navigation("ReceivedPenalties"); + + b.Navigation("ZombieAggregateClientStats"); + + b.Navigation("ZombieClientStats"); + + b.Navigation("ZombieMatchClientStats"); + + b.Navigation("ZombieMatches"); + + b.Navigation("ZombieRoundClientStats"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => + { + b.Navigation("PredictedViewAngles"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientRatingHistory", b => + { + b.Navigation("Ratings"); + }); + + modelBuilder.Entity("Data.Models.Client.Stats.EFClientStatistics", b => + { + b.Navigation("HitLocations"); + }); + + modelBuilder.Entity("Data.Models.EFAliasLink", b => + { + b.Navigation("Children"); + + b.Navigation("ReceivedPenalties"); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatch", b => + { + b.Navigation("ClientStats"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.cs b/Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.cs new file mode 100644 index 000000000..2bf24e294 --- /dev/null +++ b/Data/Migrations/Sqlite/20230502032705_AddZombieStatsInitial.cs @@ -0,0 +1,230 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Data.Migrations.Sqlite +{ + public partial class AddZombieStatsInitial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "EFZombieMatch", + columns: table => new + { + ZombieMatchId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + MapId = table.Column(type: "INTEGER", nullable: true), + ServerId = table.Column(type: "INTEGER", nullable: true), + MatchStartDate = table.Column(type: "TEXT", nullable: false), + MatchEndDate = table.Column(type: "TEXT", nullable: true), + EFClientClientId = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFZombieMatch", x => x.ZombieMatchId); + table.ForeignKey( + name: "FK_EFZombieMatch_EFClients_EFClientClientId", + column: x => x.EFClientClientId, + principalTable: "EFClients", + principalColumn: "ClientId"); + table.ForeignKey( + name: "FK_EFZombieMatch_EFMaps_MapId", + column: x => x.MapId, + principalTable: "EFMaps", + principalColumn: "MapId"); + table.ForeignKey( + name: "FK_EFZombieMatch_EFServers_ServerId", + column: x => x.ServerId, + principalTable: "EFServers", + principalColumn: "ServerId"); + }); + + migrationBuilder.CreateTable( + name: "EFZombieClientStat", + columns: table => new + { + ZombieClientStatId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + MatchId = table.Column(type: "INTEGER", nullable: true), + ClientId = table.Column(type: "INTEGER", nullable: false), + Kills = table.Column(type: "INTEGER", nullable: false), + Deaths = table.Column(type: "INTEGER", nullable: false), + DamageDealt = table.Column(type: "INTEGER", nullable: false), + DamageReceived = table.Column(type: "INTEGER", nullable: false), + Headshots = table.Column(type: "INTEGER", nullable: false), + Melees = table.Column(type: "INTEGER", nullable: false), + Downs = table.Column(type: "INTEGER", nullable: false), + Revives = table.Column(type: "INTEGER", nullable: false), + PointsEarned = table.Column(type: "INTEGER", nullable: false), + PointsSpent = table.Column(type: "INTEGER", nullable: false), + PerksConsumed = table.Column(type: "INTEGER", nullable: false), + PowerupsGrabbed = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_EFZombieClientStat", x => x.ZombieClientStatId); + table.ForeignKey( + name: "FK_EFZombieClientStat_EFClients_ClientId", + column: x => x.ClientId, + principalTable: "EFClients", + principalColumn: "ClientId", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_EFZombieClientStat_EFZombieMatch_MatchId", + column: x => x.MatchId, + principalTable: "EFZombieMatch", + principalColumn: "ZombieMatchId"); + }); + + migrationBuilder.CreateTable( + name: "EFZombieAggregateClientStat", + columns: table => new + { + ZombieClientStatId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + AverageKillsPerDown = table.Column(type: "REAL", nullable: false), + AverageDowns = table.Column(type: "REAL", nullable: false), + AverageRevives = table.Column(type: "REAL", nullable: false), + HeadshotPercentage = table.Column(type: "REAL", nullable: false), + AlivePercentage = table.Column(type: "REAL", nullable: false), + AverageMelees = table.Column(type: "REAL", nullable: false), + AverageRoundReached = table.Column(type: "REAL", nullable: false), + AveragePoints = table.Column(type: "REAL", nullable: false), + HighestRound = table.Column(type: "INTEGER", nullable: false), + TotalRoundsPlayed = table.Column(type: "INTEGER", nullable: false), + TotalMatchesPlayed = table.Column(type: "INTEGER", nullable: false), + RankingMetric = table.Column(type: "REAL", nullable: false), + EFClientClientId = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFZombieAggregateClientStat", x => x.ZombieClientStatId); + table.ForeignKey( + name: "FK_EFZombieAggregateClientStat_EFClients_EFClientClientId", + column: x => x.EFClientClientId, + principalTable: "EFClients", + principalColumn: "ClientId"); + table.ForeignKey( + name: "FK_EFZombieAggregateClientStat_EFZombieClientStat_ZombieClientStatId", + column: x => x.ZombieClientStatId, + principalTable: "EFZombieClientStat", + principalColumn: "ZombieClientStatId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFZombieMatchClientStat", + columns: table => new + { + ZombieClientStatId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + EFClientClientId = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFZombieMatchClientStat", x => x.ZombieClientStatId); + table.ForeignKey( + name: "FK_EFZombieMatchClientStat_EFClients_EFClientClientId", + column: x => x.EFClientClientId, + principalTable: "EFClients", + principalColumn: "ClientId"); + table.ForeignKey( + name: "FK_EFZombieMatchClientStat_EFZombieClientStat_ZombieClientStatId", + column: x => x.ZombieClientStatId, + principalTable: "EFZombieClientStat", + principalColumn: "ZombieClientStatId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "EFZombieRoundClientStat", + columns: table => new + { + ZombieClientStatId = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + StartTime = table.Column(type: "TEXT", nullable: false), + EndTime = table.Column(type: "TEXT", nullable: true), + Duration = table.Column(type: "TEXT", nullable: true), + TimeAlive = table.Column(type: "TEXT", nullable: true), + RoundNumber = table.Column(type: "INTEGER", nullable: false), + Points = table.Column(type: "INTEGER", nullable: false), + EFClientClientId = table.Column(type: "INTEGER", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_EFZombieRoundClientStat", x => x.ZombieClientStatId); + table.ForeignKey( + name: "FK_EFZombieRoundClientStat_EFClients_EFClientClientId", + column: x => x.EFClientClientId, + principalTable: "EFClients", + principalColumn: "ClientId"); + table.ForeignKey( + name: "FK_EFZombieRoundClientStat_EFZombieClientStat_ZombieClientStatId", + column: x => x.ZombieClientStatId, + principalTable: "EFZombieClientStat", + principalColumn: "ZombieClientStatId", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieAggregateClientStat_EFClientClientId", + table: "EFZombieAggregateClientStat", + column: "EFClientClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieClientStat_ClientId", + table: "EFZombieClientStat", + column: "ClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieClientStat_MatchId", + table: "EFZombieClientStat", + column: "MatchId"); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieMatch_EFClientClientId", + table: "EFZombieMatch", + column: "EFClientClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieMatch_MapId", + table: "EFZombieMatch", + column: "MapId"); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieMatch_ServerId", + table: "EFZombieMatch", + column: "ServerId"); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieMatchClientStat_EFClientClientId", + table: "EFZombieMatchClientStat", + column: "EFClientClientId"); + + migrationBuilder.CreateIndex( + name: "IX_EFZombieRoundClientStat_EFClientClientId", + table: "EFZombieRoundClientStat", + column: "EFClientClientId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "EFZombieAggregateClientStat"); + + migrationBuilder.DropTable( + name: "EFZombieMatchClientStat"); + + migrationBuilder.DropTable( + name: "EFZombieRoundClientStat"); + + migrationBuilder.DropTable( + name: "EFZombieClientStat"); + + migrationBuilder.DropTable( + name: "EFZombieMatch"); + } + } +} diff --git a/Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs b/Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs index 8bd01723a..f45226322 100644 --- a/Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs +++ b/Data/Migrations/Sqlite/SqliteDatabaseContextModelSnapshot.cs @@ -812,6 +812,7 @@ namespace Data.Migrations.Sqlite b.Property("SearchableIPAddress") .ValueGeneratedOnAddOrUpdate() + .HasMaxLength(255) .HasColumnType("TEXT") .HasComputedColumnSql("((IPAddress & 255) || '.' || ((IPAddress >> 8) & 255)) || '.' || ((IPAddress >> 16) & 255) || '.' || ((IPAddress >> 24) & 255)", true); @@ -1160,6 +1161,185 @@ namespace Data.Migrations.Sqlite b.ToTable("Vector3", (string)null); }); + modelBuilder.Entity("Data.Models.Zombie.ZombieClientStat", b => + { + b.Property("ZombieClientStatId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClientId") + .HasColumnType("INTEGER"); + + b.Property("DamageDealt") + .HasColumnType("INTEGER"); + + b.Property("DamageReceived") + .HasColumnType("INTEGER"); + + b.Property("Deaths") + .HasColumnType("INTEGER"); + + b.Property("Downs") + .HasColumnType("INTEGER"); + + b.Property("Headshots") + .HasColumnType("INTEGER"); + + b.Property("Kills") + .HasColumnType("INTEGER"); + + b.Property("MatchId") + .HasColumnType("INTEGER"); + + b.Property("Melees") + .HasColumnType("INTEGER"); + + b.Property("PerksConsumed") + .HasColumnType("INTEGER"); + + b.Property("PointsEarned") + .HasColumnType("INTEGER"); + + b.Property("PointsSpent") + .HasColumnType("INTEGER"); + + b.Property("PowerupsGrabbed") + .HasColumnType("INTEGER"); + + b.Property("Revives") + .HasColumnType("INTEGER"); + + b.HasKey("ZombieClientStatId"); + + b.HasIndex("ClientId"); + + b.HasIndex("MatchId"); + + b.ToTable("EFZombieClientStat", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatch", b => + { + b.Property("ZombieMatchId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.Property("MapId") + .HasColumnType("INTEGER"); + + b.Property("MatchEndDate") + .HasColumnType("TEXT"); + + b.Property("MatchStartDate") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.HasKey("ZombieMatchId"); + + b.HasIndex("EFClientClientId"); + + b.HasIndex("MapId"); + + b.HasIndex("ServerId"); + + b.ToTable("EFZombieMatch", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieAggregateClientStat", b => + { + b.HasBaseType("Data.Models.Zombie.ZombieClientStat"); + + b.Property("AlivePercentage") + .HasColumnType("REAL"); + + b.Property("AverageDowns") + .HasColumnType("REAL"); + + b.Property("AverageKillsPerDown") + .HasColumnType("REAL"); + + b.Property("AverageMelees") + .HasColumnType("REAL"); + + b.Property("AveragePoints") + .HasColumnType("REAL"); + + b.Property("AverageRevives") + .HasColumnType("REAL"); + + b.Property("AverageRoundReached") + .HasColumnType("REAL"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.Property("HeadshotPercentage") + .HasColumnType("REAL"); + + b.Property("HighestRound") + .HasColumnType("INTEGER"); + + b.Property("RankingMetric") + .HasColumnType("REAL"); + + b.Property("TotalMatchesPlayed") + .HasColumnType("INTEGER"); + + b.Property("TotalRoundsPlayed") + .HasColumnType("INTEGER"); + + b.HasIndex("EFClientClientId"); + + b.ToTable("EFZombieAggregateClientStat", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatchClientStat", b => + { + b.HasBaseType("Data.Models.Zombie.ZombieClientStat"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.HasIndex("EFClientClientId"); + + b.ToTable("EFZombieMatchClientStat", (string)null); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieRoundClientStat", b => + { + b.HasBaseType("Data.Models.Zombie.ZombieClientStat"); + + b.Property("Duration") + .HasColumnType("TEXT"); + + b.Property("EFClientClientId") + .HasColumnType("INTEGER"); + + b.Property("EndTime") + .HasColumnType("TEXT"); + + b.Property("Points") + .HasColumnType("INTEGER"); + + b.Property("RoundNumber") + .HasColumnType("INTEGER"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("TimeAlive") + .HasColumnType("TEXT"); + + b.HasIndex("EFClientClientId"); + + b.ToTable("EFZombieRoundClientStat", (string)null); + }); + modelBuilder.Entity("Data.Models.Client.EFACSnapshotVector3", b => { b.HasOne("Data.Models.Client.Stats.EFACSnapshot", "Snapshot") @@ -1601,6 +1781,81 @@ namespace Data.Migrations.Sqlite b.Navigation("Server"); }); + modelBuilder.Entity("Data.Models.Zombie.ZombieClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", "Client") + .WithMany("ZombieClientStats") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Data.Models.Zombie.ZombieMatch", "Match") + .WithMany("ClientStats") + .HasForeignKey("MatchId"); + + b.Navigation("Client"); + + b.Navigation("Match"); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatch", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieMatches") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Client.Stats.Reference.EFMap", "Map") + .WithMany() + .HasForeignKey("MapId"); + + b.HasOne("Data.Models.Server.EFServer", "Server") + .WithMany() + .HasForeignKey("ServerId"); + + b.Navigation("Map"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieAggregateClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieAggregateClientStats") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Zombie.ZombieClientStat", null) + .WithOne() + .HasForeignKey("Data.Models.Zombie.ZombieAggregateClientStat", "ZombieClientStatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatchClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieMatchClientStats") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Zombie.ZombieClientStat", null) + .WithOne() + .HasForeignKey("Data.Models.Zombie.ZombieMatchClientStat", "ZombieClientStatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieRoundClientStat", b => + { + b.HasOne("Data.Models.Client.EFClient", null) + .WithMany("ZombieRoundClientStats") + .HasForeignKey("EFClientClientId"); + + b.HasOne("Data.Models.Zombie.ZombieClientStat", null) + .WithOne() + .HasForeignKey("Data.Models.Zombie.ZombieRoundClientStat", "ZombieClientStatId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Data.Models.Client.EFClient", b => { b.Navigation("AdministeredPenalties"); @@ -1608,6 +1863,16 @@ namespace Data.Migrations.Sqlite b.Navigation("Meta"); b.Navigation("ReceivedPenalties"); + + b.Navigation("ZombieAggregateClientStats"); + + b.Navigation("ZombieClientStats"); + + b.Navigation("ZombieMatchClientStats"); + + b.Navigation("ZombieMatches"); + + b.Navigation("ZombieRoundClientStats"); }); modelBuilder.Entity("Data.Models.Client.Stats.EFACSnapshot", b => @@ -1631,6 +1896,11 @@ namespace Data.Migrations.Sqlite b.Navigation("ReceivedPenalties"); }); + + modelBuilder.Entity("Data.Models.Zombie.ZombieMatch", b => + { + b.Navigation("ClientStats"); + }); #pragma warning restore 612, 618 } } diff --git a/Data/Models/Client/EFClient.cs b/Data/Models/Client/EFClient.cs index 55fe19b66..6cb114686 100644 --- a/Data/Models/Client/EFClient.cs +++ b/Data/Models/Client/EFClient.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Zombie; namespace Data.Models.Client { @@ -83,5 +84,10 @@ namespace Data.Models.Client public virtual ICollection Meta { get; set; } public virtual ICollection ReceivedPenalties { get; set; } public virtual ICollection AdministeredPenalties { get; set; } + public virtual ICollection ZombieAggregateClientStats { get; set; } + public virtual ICollection ZombieClientStats { get; set; } + public virtual ICollection ZombieMatches { get; set; } + public virtual ICollection ZombieMatchClientStats { get; set; } + public virtual ICollection ZombieRoundClientStats { get; set; } } } diff --git a/Data/Models/Zombie/ZombieAggregateClientStat.cs b/Data/Models/Zombie/ZombieAggregateClientStat.cs new file mode 100644 index 000000000..2410907c1 --- /dev/null +++ b/Data/Models/Zombie/ZombieAggregateClientStat.cs @@ -0,0 +1,27 @@ +namespace Data.Models.Zombie; + +public class ZombieAggregateClientStat : ZombieClientStat +{ + #region Average + + public double AverageKillsPerDown { get; set; } + public double AverageDowns { get; set; } + public double AverageRevives { get; set; } + public double HeadshotPercentage { get; set; } + public double AlivePercentage { get; set; } + public double AverageMelees { get; set; } + public double AverageRoundReached { get; set; } + public double AveragePoints { get; set; } + + #endregion + + #region Totals + + public int HighestRound { get; set; } + public int TotalRoundsPlayed { get; set; } + public int TotalMatchesPlayed { get; set; } + + #endregion + + public double RankingMetric { get; set; } +} diff --git a/Data/Models/Zombie/ZombieClientStat.cs b/Data/Models/Zombie/ZombieClientStat.cs new file mode 100644 index 000000000..b055f810a --- /dev/null +++ b/Data/Models/Zombie/ZombieClientStat.cs @@ -0,0 +1,34 @@ +#nullable enable +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Client; + +namespace Data.Models.Zombie; + +public abstract class ZombieClientStat +{ + [Key] + public long ZombieClientStatId { get; set; } + + public int? MatchId { get; set; } + + [ForeignKey(nameof(MatchId))] + public virtual ZombieMatch? Match { get; set; } + + public int ClientId { get; set; } + [ForeignKey(nameof(ClientId))] + public virtual EFClient? Client { get; set; } + + public int Kills { get; set; } + public int Deaths { get; set; } + public int DamageDealt { get; set; } + public int DamageReceived { get; set; } + public int Headshots { get; set; } + public int Melees { get; set; } + public int Downs { get; set; } + public int Revives { get; set; } + public int PointsEarned { get; set; } + public int PointsSpent { get; set; } + public int PerksConsumed { get; set; } + public int PowerupsGrabbed { get; set; } +} diff --git a/Data/Models/Zombie/ZombieMatch.cs b/Data/Models/Zombie/ZombieMatch.cs new file mode 100644 index 000000000..8c987476a --- /dev/null +++ b/Data/Models/Zombie/ZombieMatch.cs @@ -0,0 +1,28 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Data.Models.Client.Stats.Reference; +using Data.Models.Server; + +namespace Data.Models.Zombie; + +public class ZombieMatch +{ + [Key] + public int ZombieMatchId { get; set; } + + public int? MapId { get; set; } + [ForeignKey(nameof(MapId))] + public virtual EFMap? Map { get; set; } + + public long? ServerId { get; set; } + [ForeignKey(nameof(ServerId))] + public virtual EFServer? Server { get; set; } + + public virtual ICollection? ClientStats { get; set; } + + public DateTimeOffset MatchStartDate { get; set; } = DateTimeOffset.UtcNow; + public DateTimeOffset? MatchEndDate { get; set; } +} diff --git a/Data/Models/Zombie/ZombieMatchClientStat.cs b/Data/Models/Zombie/ZombieMatchClientStat.cs new file mode 100644 index 000000000..bb24206fc --- /dev/null +++ b/Data/Models/Zombie/ZombieMatchClientStat.cs @@ -0,0 +1,6 @@ +namespace Data.Models.Zombie; + +public class ZombieMatchClientStat : ZombieClientStat +{ + +} diff --git a/Data/Models/Zombie/ZombieRoundClientStat.cs b/Data/Models/Zombie/ZombieRoundClientStat.cs new file mode 100644 index 000000000..20ab36218 --- /dev/null +++ b/Data/Models/Zombie/ZombieRoundClientStat.cs @@ -0,0 +1,13 @@ +using System; + +namespace Data.Models.Zombie; + +public class ZombieRoundClientStat : ZombieClientStat +{ + public DateTimeOffset StartTime { get; set; } = DateTimeOffset.UtcNow; + public DateTimeOffset? EndTime { get; set; } + public TimeSpan? Duration { get; set; } + public TimeSpan? TimeAlive { get; set; } + public int RoundNumber { get; set; } + public int Points { get; set; } +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerConsumedPerkGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerConsumedPerkGameEvent.cs new file mode 100644 index 000000000..353e4c484 --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerConsumedPerkGameEvent.cs @@ -0,0 +1,9 @@ +using Data.Models.Client; + +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class PlayerConsumedPerkGameEvent : ClientGameEvent +{ + public EFClient Consumer => Origin; + public string PerkName { get; init; } +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDamageGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDamageGameEvent.cs new file mode 100644 index 000000000..a39780922 --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDamageGameEvent.cs @@ -0,0 +1,6 @@ +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class PlayerDamageGameEvent : ClientDamageEvent +{ + +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDownedGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDownedGameEvent.cs new file mode 100644 index 000000000..15d18e250 --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerDownedGameEvent.cs @@ -0,0 +1,6 @@ +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class PlayerDownedGameEvent : ClientGameEvent +{ + +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerGrabbedPowerupameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerGrabbedPowerupameEvent.cs new file mode 100644 index 000000000..ebc198c6f --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerGrabbedPowerupameEvent.cs @@ -0,0 +1,9 @@ +using Data.Models.Client; + +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class PlayerGrabbedPowerupGameEvent : ClientGameEvent +{ + public EFClient Grabber => Origin; + public string PowerupName { get; init; } +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerKilledGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerKilledGameEvent.cs new file mode 100644 index 000000000..d5e53f5ee --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerKilledGameEvent.cs @@ -0,0 +1,9 @@ +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class PlayerKilledGameEvent : PlayerDamageGameEvent +{ + public PlayerKilledGameEvent() + { + RequiredEntity = EventRequiredEntity.Target; + } +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRevivedGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRevivedGameEvent.cs new file mode 100644 index 000000000..2b9692dff --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRevivedGameEvent.cs @@ -0,0 +1,9 @@ +using Data.Models.Client; + +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class PlayerRevivedGameEvent : ClientGameEvent +{ + public EFClient Reviver => Origin; + public EFClient Revived => Target; +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRoundDataGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRoundDataGameEvent.cs new file mode 100644 index 000000000..5ccb088ee --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/PlayerRoundDataGameEvent.cs @@ -0,0 +1,8 @@ +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class PlayerRoundDataGameEvent : ClientGameEvent +{ + public int TotalScore { get; init; } + public int CurrentScore { get; init; } + public bool IsGameOver { get; init; } +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/RoundCompleteGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/RoundCompleteGameEvent.cs new file mode 100644 index 000000000..ed6974de8 --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/RoundCompleteGameEvent.cs @@ -0,0 +1,6 @@ +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class RoundCompleteGameEvent : GameEventV2 +{ + public int RoundNumber { get; init; } +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieDamageGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieDamageGameEvent.cs new file mode 100644 index 000000000..c20ebe051 --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieDamageGameEvent.cs @@ -0,0 +1,6 @@ +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class ZombieDamageGameEvent : ClientDamageEvent +{ + +} diff --git a/SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieKilledGameEvent.cs b/SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieKilledGameEvent.cs new file mode 100644 index 000000000..54dce87ab --- /dev/null +++ b/SharedLibraryCore/Events/Game/GameScript/Zombie/ZombieKilledGameEvent.cs @@ -0,0 +1,9 @@ +namespace SharedLibraryCore.Events.Game.GameScript.Zombie; + +public class ZombieKilledGameEvent : ZombieDamageGameEvent +{ + public ZombieKilledGameEvent() + { + RequiredEntity = EventRequiredEntity.Origin; + } +}