diff --git a/apps/backend/Jobs/Character/CharacterAchievementsJob.cs b/apps/backend/Jobs/Character/CharacterAchievementsJob.cs index edaba2cda..414006e36 100644 --- a/apps/backend/Jobs/Character/CharacterAchievementsJob.cs +++ b/apps/backend/Jobs/Character/CharacterAchievementsJob.cs @@ -23,6 +23,31 @@ public override async Task Run(string[] data) { var timer = new JankTimer(); + if (_query?.AccountId == null) + { + throw new InvalidDataException("AccountId is null"); + } + + int accountId = _query.AccountId.Value; + + string lockKey = string.Format(RedisKeys.AccountAchievements, accountId); + string lockValue = Guid.NewGuid().ToString("N"); + try + { + // Attempt to get exclusive scheduler lock + bool lockSuccess = await JobRepository.AcquireLockAsync(lockKey, lockValue, TimeSpan.FromMinutes(1)); + if (!lockSuccess) + { + Logger.Debug("Skipping achievements, lock failed"); + return; + } + } + catch (Exception ex) + { + Logger.Error(ex, "Kaboom!"); + return; + } + // Fetch API data ApiCharacterAchievements resultData; var uri = GenerateUri(_query, ApiPath); @@ -43,6 +68,17 @@ public override async Task Run(string[] data) return; } + // Fetch account data + var paAchievements = await Context.PlayerAccountAchievements.FindAsync(accountId); + if (paAchievements == null) + { + paAchievements = new PlayerAccountAchievements + { + AccountId = accountId, + }; + Context.PlayerAccountAchievements.Add(paAchievements); + } + // Fetch character data var pcAchievements = await Context.PlayerCharacterAchievements.FindAsync(_query.CharacterId); if (pcAchievements == null) @@ -78,6 +114,7 @@ public override async Task Run(string[] data) RecurseCriteria(criteria, dataAchievement.Criteria?.ChildCriteria); } + // Achievements go in account data var sortedAchievements = cheevs .OrderBy(kvp => kvp.Key) .ToArray(); @@ -88,16 +125,19 @@ public override async Task Run(string[] data) .Select(kvp => kvp.Value) .ToList(); - if (pcAchievements.AchievementIds == null || !achievementIds.SequenceEqual(pcAchievements.AchievementIds)) + byte[] compressedAchievementIds = SerializationUtilities.SerializeToBitmap(achievementIds); + + if (paAchievements.CompressedAchievementIds == null || !compressedAchievementIds.SequenceEqual(paAchievements.CompressedAchievementIds)) { - pcAchievements.AchievementIds = achievementIds; + paAchievements.CompressedAchievementIds = compressedAchievementIds; } - if (pcAchievements.AchievementTimestamps == null || !achievementTimestamps.SequenceEqual(pcAchievements.AchievementTimestamps)) + if (paAchievements.AchievementTimestamps == null || !achievementTimestamps.SequenceEqual(paAchievements.AchievementTimestamps)) { - pcAchievements.AchievementTimestamps = achievementTimestamps; + paAchievements.AchievementTimestamps = achievementTimestamps; } + // Criteria go in character data var sortedCriteria = criteria .Where(kvp => kvp.Value.Item2 || kvp.Value.Item1 > 0) .OrderBy(kvp => kvp.Key) @@ -112,9 +152,12 @@ public override async Task Run(string[] data) .Select(kvp => kvp.Value.Item2) .ToList(); - if (pcAchievements.CriteriaIds == null || !criteriaIds.SequenceEqual(pcAchievements.CriteriaIds)) + byte[] compressedCriteriaIds = SerializationUtilities.SerializeToBitmap(criteriaIds); + + if (pcAchievements.CompressedCriteriaIds == null || !compressedCriteriaIds.SequenceEqual(pcAchievements.CompressedCriteriaIds)) { - pcAchievements.CriteriaIds = criteriaIds; + pcAchievements.CriteriaIds = null; + pcAchievements.CompressedCriteriaIds = compressedCriteriaIds; } if (pcAchievements.CriteriaAmounts == null || !criteriaAmounts.SequenceEqual(pcAchievements.CriteriaAmounts)) diff --git a/apps/backend/Jobs/Character/CharacterMountsJob.cs b/apps/backend/Jobs/Character/CharacterMountsJob.cs index 94b698135..90256773f 100644 --- a/apps/backend/Jobs/Character/CharacterMountsJob.cs +++ b/apps/backend/Jobs/Character/CharacterMountsJob.cs @@ -1,5 +1,6 @@ using System.Net.Http; using Wowthing.Backend.Models.API.Character; +using Wowthing.Lib.Constants; using Wowthing.Lib.Models.Player; using Wowthing.Lib.Models.Query; @@ -26,7 +27,7 @@ public override async Task Run(string[] data) int accountId = _query.AccountId.Value; - string lockKey = $"account_mounts:{accountId}"; + string lockKey = string.Format(RedisKeys.AccountMounts, accountId); string lockValue = Guid.NewGuid().ToString("N"); try { @@ -34,7 +35,7 @@ public override async Task Run(string[] data) bool lockSuccess = await JobRepository.AcquireLockAsync(lockKey, lockValue, TimeSpan.FromMinutes(1)); if (!lockSuccess) { - Logger.Debug("Skipping pets, lock failed"); + Logger.Debug("Skipping mounts, lock failed"); return; } } @@ -63,7 +64,7 @@ public override async Task Run(string[] data) return; } - // Fetch character data + // Fetch account data var paMounts = await Context.PlayerAccountMounts.FindAsync(accountId); if (paMounts == null) { diff --git a/apps/frontend/components/home/view-switcher/Delves.svelte b/apps/frontend/components/home/view-switcher/Delves.svelte index 05d5d9dbf..48a14614d 100644 --- a/apps/frontend/components/home/view-switcher/Delves.svelte +++ b/apps/frontend/components/home/view-switcher/Delves.svelte @@ -3,13 +3,13 @@ import { delveMap, type Delve } from '@/data/delve'; import { iconLibrary } from '@/shared/icons'; + import { settingsState } from '@/shared/state/settings.svelte'; import { componentTooltip } from '@/shared/utils/tooltips'; import { userState } from '@/user-home/state/user'; import { dynamicDataStore } from '@/user-home/stores/dynamicData'; import DelvesTooltip from './DelvesTooltip.svelte'; import IconifyWrapper from '@/shared/components/images/IconifyWrapper.svelte'; - import { settingsState } from '@/shared/state/settings.svelte'; let delves = $derived.by(() => { const dynamicDelves = dynamicDataStore.getCached(userState.general.allRegions[0]).delves; diff --git a/apps/frontend/data/icons.ts b/apps/frontend/data/icons.ts index c20077b4a..961def3ed 100644 --- a/apps/frontend/data/icons.ts +++ b/apps/frontend/data/icons.ts @@ -39,6 +39,7 @@ export const imageStrings: Record = { }; export const iconStrings: Record = { + dungeon: iconLibrary.faDungeon, exclamation: iconLibrary.mdiExclamationThick, fire: iconLibrary.mdiFire, item: iconLibrary.mdiGiftOutline, diff --git a/apps/frontend/data/tasks/events/timewalking.ts b/apps/frontend/data/tasks/events/timewalking.ts index a1422fdbf..b169a9730 100644 --- a/apps/frontend/data/tasks/events/timewalking.ts +++ b/apps/frontend/data/tasks/events/timewalking.ts @@ -13,6 +13,7 @@ export const eventTimewalking: Task = { { key: 'dungeons', name: 'Dungeons', + icon: ':time::dungeon:', minimumLevel: 10, requiredHolidays: timewalkingHolidays, questReset: DbResetType.Weekly, @@ -50,6 +51,7 @@ export const eventTimewalking: Task = { { key: 'dungeonItem', name: 'Dungeon Item', + icon: ':time::item:', requiredHolidays: timewalkingHolidays, questReset: DbResetType.Weekly, questIds: [ diff --git a/apps/frontend/shared/icons/library.ts b/apps/frontend/shared/icons/library.ts index b91457117..f85aec2ac 100644 --- a/apps/frontend/shared/icons/library.ts +++ b/apps/frontend/shared/icons/library.ts @@ -146,6 +146,7 @@ export { default as mdiGiftOutline } from '~icons/mdi/gift-outline'; export { default as mdiGhost } from '~icons/mdi/ghost'; export { default as mdiHammerWrench } from '~icons/mdi/hammer-wrench'; export { default as mdiHomeOutline } from '~icons/mdi/home-outline'; +export { default as mdiHourglass } from '~icons/mdi/hourglass'; export { default as mdiImageBrokenVariant } from '~icons/mdi/image-broken-variant'; export { default as mdiLetterC } from '~icons/mdi/alpha-c-circle-outline'; export { default as mdiLetterD } from '~icons/mdi/alpha-d-circle-outline'; diff --git a/apps/frontend/shared/icons/ui.ts b/apps/frontend/shared/icons/ui.ts index f2e23ce0f..1129aea46 100644 --- a/apps/frontend/shared/icons/ui.ts +++ b/apps/frontend/shared/icons/ui.ts @@ -11,6 +11,7 @@ export const uiIcons = { starEmpty: iconLibrary.mdiStarOutline, starHalf: iconLibrary.mdiStarHalfFull, starFull: iconLibrary.mdiStarFace, + time: iconLibrary.mdiHourglass, yes: iconLibrary.mdiCheck, circleD: iconLibrary.mynauiLetterDCircle, diff --git a/packages/csharp-lib/Constants/RedisKeys.cs b/packages/csharp-lib/Constants/RedisKeys.cs index 0b00aa3ba..7c1aa9858 100644 --- a/packages/csharp-lib/Constants/RedisKeys.cs +++ b/packages/csharp-lib/Constants/RedisKeys.cs @@ -7,6 +7,9 @@ public static class RedisKeys public const string AuctionsLock = "lock:auctions"; public const string CheckedAuctions = "checked_auctions"; + public const string AccountAchievements = "account:{0}:achievements"; + public const string AccountMounts = "account:{0}:mounts"; + public const string CharacterJobCounter = "character:{0}:jobs"; public const string UserAchievements = "user:{0}:achievements"; diff --git a/packages/csharp-lib/Contexts/WowDbContext.cs b/packages/csharp-lib/Contexts/WowDbContext.cs index 487a1309a..4f96bb5d5 100644 --- a/packages/csharp-lib/Contexts/WowDbContext.cs +++ b/packages/csharp-lib/Contexts/WowDbContext.cs @@ -62,6 +62,7 @@ public class WowDbContext : IdentityDbContext GlobalDailies { get; set; } public DbSet PlayerAccount { get; set; } + public DbSet PlayerAccountAchievements { get; set; } public DbSet PlayerAccountAddonData { get; set; } public DbSet PlayerAccountGoldSnapshot { get; set; } public DbSet PlayerAccountHeirlooms { get; set; } diff --git a/packages/csharp-lib/Migrations/20260704213450_Add_PlayerAccountAchievements.Designer.cs b/packages/csharp-lib/Migrations/20260704213450_Add_PlayerAccountAchievements.Designer.cs new file mode 100644 index 000000000..d9b07fa62 --- /dev/null +++ b/packages/csharp-lib/Migrations/20260704213450_Add_PlayerAccountAchievements.Designer.cs @@ -0,0 +1,4554 @@ +// +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Wowthing.Lib.Contexts; +using Wowthing.Lib.Enums; +using Wowthing.Lib.Models; +using Wowthing.Lib.Models.Global; +using Wowthing.Lib.Models.Player; +using Wowthing.Lib.Models.Wow; + +#nullable disable + +namespace Wowthing.Lib.Migrations +{ + [DbContext(typeof(WowDbContext))] + [Migration("20260704213450_Add_PlayerAccountAchievements")] + partial class Add_PlayerAccountAchievements + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text") + .HasColumnName("concurrency_stamp"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("normalized_name"); + + b.HasKey("Id") + .HasName("pk_asp_net_roles"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("asp_net_roles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text") + .HasColumnName("claim_type"); + + b.Property("ClaimValue") + .HasColumnType("text") + .HasColumnName("claim_value"); + + b.Property("RoleId") + .HasColumnType("bigint") + .HasColumnName("role_id"); + + b.HasKey("Id") + .HasName("pk_asp_net_role_claims"); + + b.HasIndex("RoleId") + .HasDatabaseName("ix_asp_net_role_claims_role_id"); + + b.ToTable("asp_net_role_claims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text") + .HasColumnName("claim_type"); + + b.Property("ClaimValue") + .HasColumnType("text") + .HasColumnName("claim_value"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_asp_net_user_claims"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_asp_net_user_claims_user_id"); + + b.ToTable("asp_net_user_claims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text") + .HasColumnName("login_provider"); + + b.Property("ProviderKey") + .HasColumnType("text") + .HasColumnName("provider_key"); + + b.Property("ProviderDisplayName") + .HasColumnType("text") + .HasColumnName("provider_display_name"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("LoginProvider", "ProviderKey") + .HasName("pk_asp_net_user_logins"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_asp_net_user_logins_user_id"); + + b.ToTable("asp_net_user_logins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("RoleId") + .HasColumnType("bigint") + .HasColumnName("role_id"); + + b.HasKey("UserId", "RoleId") + .HasName("pk_asp_net_user_roles"); + + b.HasIndex("RoleId") + .HasDatabaseName("ix_asp_net_user_roles_role_id"); + + b.ToTable("asp_net_user_roles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("LoginProvider") + .HasColumnType("text") + .HasColumnName("login_provider"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Value") + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("UserId", "LoginProvider", "Name") + .HasName("pk_asp_net_user_tokens"); + + b.ToTable("asp_net_user_tokens", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccessFailedCount") + .HasColumnType("integer") + .HasColumnName("access_failed_count"); + + b.Property("ApiKey") + .HasColumnType("text") + .HasColumnName("api_key"); + + b.Property("CanUseSubdomain") + .HasColumnType("boolean") + .HasColumnName("can_use_subdomain"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text") + .HasColumnName("concurrency_stamp"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("email"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean") + .HasColumnName("email_confirmed"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("LastVisit") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_visit"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean") + .HasColumnName("lockout_enabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("lockout_end"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("normalized_email"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("normalized_user_name"); + + b.Property("PasswordHash") + .HasColumnType("text") + .HasColumnName("password_hash"); + + b.Property("PhoneNumber") + .HasColumnType("text") + .HasColumnName("phone_number"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean") + .HasColumnName("phone_number_confirmed"); + + b.Property("SecurityStamp") + .HasColumnType("text") + .HasColumnName("security_stamp"); + + b.Property("Settings") + .HasColumnType("jsonb") + .HasColumnName("settings"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean") + .HasColumnName("two_factor_enabled"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("pk_asp_net_users"); + + b.HasIndex("ApiKey") + .IsUnique() + .HasDatabaseName("ix_asp_net_users_api_key"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("asp_net_users", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("text") + .HasColumnName("action"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_audit_log"); + + b.ToTable("audit_log", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.BackgroundImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Attribution") + .HasColumnType("text") + .HasColumnName("attribution"); + + b.Property("DefaultBrightness") + .HasColumnType("smallint") + .HasColumnName("default_brightness"); + + b.Property("DefaultSaturate") + .HasColumnType("smallint") + .HasColumnName("default_saturate"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Filename") + .HasColumnType("text") + .HasColumnName("filename"); + + b.Property("RoleId") + .HasColumnType("bigint") + .HasColumnName("role_id"); + + b.HasKey("Id") + .HasName("pk_background_image"); + + b.HasIndex("RoleId") + .HasDatabaseName("ix_background_image_role_id"); + + b.ToTable("background_image", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Global.GlobalDailies", b => + { + b.Property("Expansion") + .HasColumnType("integer") + .HasColumnName("expansion"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.PrimitiveCollection>("QuestExpires") + .HasColumnType("integer[]") + .HasColumnName("quest_expires"); + + b.PrimitiveCollection>("QuestIds") + .HasColumnType("integer[]") + .HasColumnName("quest_ids"); + + b.Property>("QuestRewards") + .HasColumnType("jsonb") + .HasColumnName("quest_rewards"); + + b.HasKey("Expansion", "Region") + .HasName("pk_global_dailies"); + + b.ToTable("global_dailies", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Image", b => + { + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Format") + .HasColumnType("smallint") + .HasColumnName("format"); + + b.Property("Data") + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Sha256") + .HasColumnType("char(64)") + .HasColumnName("sha256"); + + b.HasKey("Type", "Id", "Format") + .HasName("pk_image"); + + b.HasIndex("Type", "Sha256", "Format") + .HasDatabaseName("ix_image_type_sha256_format"); + + b.ToTable("image", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.LanguageString", b => + { + b.Property("Language") + .HasColumnType("smallint") + .HasColumnName("language"); + + b.Property("Type") + .HasColumnType("smallint") + .HasColumnName("type"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("String") + .HasColumnType("text") + .HasColumnName("string"); + + b.HasKey("Language", "Type", "Id") + .HasName("pk_language_string"); + + b.HasIndex("String") + .HasDatabaseName("ix_language_string_string"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("String"), "gin"); + NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("String"), new[] { "gin_trgm_ops" }); + + b.HasIndex("Language", "Type", "Id") + .HasDatabaseName("ix_language_string_language_type_id"); + + b.ToTable("language_string", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.MiscAggregate", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ReportType") + .HasColumnType("smallint") + .HasColumnName("report_type"); + + b.Property("JsonData") + .HasColumnType("text") + .HasColumnName("json_data"); + + b.HasKey("Region", "ReportType") + .HasName("pk_misc_aggregate"); + + b.ToTable("misc_aggregate", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.MiscReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("data"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ReportType") + .HasColumnType("smallint") + .HasColumnName("report_type"); + + b.Property("ReportedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reported_at"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_misc_report"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_misc_report_user_id"); + + b.HasIndex("ReportType", "Region", "ExpiresAt") + .IsDescending(false, false, true) + .HasDatabaseName("ix_misc_report_report_type_region_expires_at"); + + b.ToTable("misc_report", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint") + .HasColumnName("account_id"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Tag") + .HasColumnType("text") + .HasColumnName("tag"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_player_account"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_player_account_user_id"); + + b.HasIndex("Region", "AccountId") + .IsUnique() + .HasDatabaseName("ix_player_account_region_account_id"); + + b.ToTable("player_account", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAchievements", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("AchievementTimestamps") + .HasColumnType("integer[]") + .HasColumnName("achievement_timestamps"); + + b.Property("CompressedAchievementIds") + .HasColumnType("bytea") + .HasColumnName("compressed_achievement_ids"); + + b.HasKey("AccountId") + .HasName("pk_player_account_achievements"); + + b.ToTable("player_account_achievements", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAddonData", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property>>("Decor") + .HasColumnType("jsonb") + .HasColumnName("decor"); + + b.Property("DecorScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("decor_scanned_at"); + + b.Property>("Heirlooms") + .HasColumnType("jsonb") + .HasColumnName("heirlooms"); + + b.Property("HonorCurrent") + .HasColumnType("smallint") + .HasColumnName("honor_current"); + + b.Property("HonorLevel") + .HasColumnType("smallint") + .HasColumnName("honor_level"); + + b.Property("HonorMax") + .HasColumnType("smallint") + .HasColumnName("honor_max"); + + b.PrimitiveCollection>("Illusions") + .HasColumnType("integer[]") + .HasColumnName("illusions"); + + b.PrimitiveCollection>("Quests") + .HasColumnType("integer[]") + .HasColumnName("quests"); + + b.Property>("Reputations") + .HasColumnType("jsonb") + .HasColumnName("reputations"); + + b.Property("ReputationsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reputations_scanned_at"); + + b.HasKey("AccountId") + .HasName("pk_player_account_addon_data"); + + b.ToTable("player_account_addon_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountGoldSnapshot", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_player_account_gold_snapshot"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_player_account_gold_snapshot_account_id"); + + b.ToTable("player_account_gold_snapshot", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountHeirlooms", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property>("Heirlooms") + .HasColumnType("jsonb") + .HasColumnName("heirlooms"); + + b.HasKey("AccountId") + .HasName("pk_player_account_heirlooms"); + + b.ToTable("player_account_heirlooms", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountMounts", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("MountIds") + .HasColumnType("integer[]") + .HasColumnName("mount_ids"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("AccountId") + .HasName("pk_player_account_mounts"); + + b.ToTable("player_account_mounts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountPets", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property>("Pets") + .HasColumnType("jsonb") + .HasColumnName("pets"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("AccountId") + .HasName("pk_player_account_pets"); + + b.ToTable("player_account_pets", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountToys", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("ToyIds") + .HasColumnType("integer[]") + .HasColumnName("toy_ids"); + + b.HasKey("AccountId") + .HasName("pk_player_account_toys"); + + b.ToTable("player_account_toys", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogIds", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("Ids") + .HasColumnType("integer[]") + .HasColumnName("ids"); + + b.HasKey("AccountId") + .HasName("pk_player_account_transmog_ids"); + + b.ToTable("player_account_transmog_ids", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogSources", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("Sources") + .HasColumnType("text[]") + .HasColumnName("sources"); + + b.HasKey("AccountId") + .HasName("pk_player_account_transmog_sources"); + + b.ToTable("player_account_transmog_sources", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("ActiveSpecId") + .HasColumnType("integer") + .HasColumnName("active_spec_id"); + + b.Property("ActiveTitleId") + .HasColumnType("integer") + .HasColumnName("active_title_id"); + + b.Property("AverageItemLevel") + .HasColumnType("integer") + .HasColumnName("average_item_level"); + + b.Property("CharacterId") + .HasColumnType("bigint") + .HasColumnName("character_id"); + + b.Property("ChromieTime") + .HasColumnType("integer") + .HasColumnName("chromie_time"); + + b.Property("ClassId") + .HasColumnType("integer") + .HasColumnName("class_id"); + + b.Property("Copper") + .HasColumnType("bigint") + .HasColumnName("copper"); + + b.Property("EquippedItemLevel") + .HasColumnType("integer") + .HasColumnName("equipped_item_level"); + + b.Property("Experience") + .HasColumnType("integer") + .HasColumnName("experience"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.Property("Gender") + .HasColumnType("integer") + .HasColumnName("gender"); + + b.Property("GuildId") + .HasColumnType("integer") + .HasColumnName("guild_id"); + + b.Property("IsResting") + .HasColumnType("boolean") + .HasColumnName("is_resting"); + + b.Property("IsWarMode") + .HasColumnType("boolean") + .HasColumnName("is_war_mode"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("LastApiModified") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_modified"); + + b.Property("LastSeenAddon") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_addon"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("PlayedTotal") + .HasColumnType("integer") + .HasColumnName("played_total"); + + b.Property("RaceId") + .HasColumnType("integer") + .HasColumnName("race_id"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property("RestedExperience") + .HasColumnType("integer") + .HasColumnName("rested_experience"); + + b.Property("ShouldUpdate") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("should_update"); + + b.HasKey("Id") + .HasName("pk_player_character"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_player_character_account_id"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_player_character_guild_id"); + + b.HasIndex("LastApiCheck") + .HasDatabaseName("ix_player_character_last_api_check") + .HasFilter("should_update = true AND account_id IS NOT NULL"); + + NpgsqlIndexBuilderExtensions.IncludeProperties(b.HasIndex("LastApiCheck"), new[] { "Id", "AccountId", "Name", "LastApiModified" }); + + b.HasIndex("CharacterId", "LastSeenAddon") + .HasDatabaseName("ix_player_character_character_id_last_seen_addon") + .HasFilter("account_id IS NOT NULL"); + + b.HasIndex("RealmId", "Name") + .IsUnique() + .HasDatabaseName("ix_player_character_realm_id_name"); + + b.ToTable("player_character", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAchievements", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("AchievementIds") + .HasColumnType("integer[]") + .HasColumnName("achievement_ids"); + + b.PrimitiveCollection>("AchievementTimestamps") + .HasColumnType("integer[]") + .HasColumnName("achievement_timestamps"); + + b.PrimitiveCollection>("CriteriaAmounts") + .HasColumnType("bigint[]") + .HasColumnName("criteria_amounts"); + + b.PrimitiveCollection>("CriteriaCompleted") + .HasColumnType("boolean[]") + .HasColumnName("criteria_completed"); + + b.PrimitiveCollection>("CriteriaIds") + .HasColumnType("integer[]") + .HasColumnName("criteria_ids"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_achievements"); + + b.ToTable("player_character_achievements", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonAchievements", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Achievements") + .HasColumnType("jsonb") + .HasColumnName("achievements"); + + b.Property("ScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_achievements"); + + b.ToTable("player_character_addon_achievements", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonData", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Auras") + .HasColumnType("jsonb") + .HasColumnName("auras"); + + b.Property("BagsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("bags_scanned_at"); + + b.Property("BankScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("bank_scanned_at"); + + b.Property("BankTabs") + .HasColumnType("smallint") + .HasColumnName("bank_tabs"); + + b.Property("BindLocation") + .HasColumnType("text") + .HasColumnName("bind_location"); + + b.Property>("Currencies") + .HasColumnType("jsonb") + .HasColumnName("currencies"); + + b.Property("CurrenciesScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("currencies_scanned_at"); + + b.Property("CurrenciesTransferredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("currencies_transferred_at"); + + b.Property("CurrentLocation") + .HasColumnType("text") + .HasColumnName("current_location"); + + b.Property("DailyReset") + .HasColumnType("timestamp with time zone") + .HasColumnName("daily_reset"); + + b.Property>("EquippedItems") + .HasColumnType("jsonb") + .HasColumnName("equipped_items"); + + b.Property>>>("GarrisonTrees") + .HasColumnType("jsonb") + .HasColumnName("garrison_trees"); + + b.Property("GarrisonTreesScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("garrison_trees_scanned_at"); + + b.Property>("Garrisons") + .HasColumnType("jsonb") + .HasColumnName("garrisons"); + + b.Property>("HighestItemLevel") + .HasColumnType("jsonb") + .HasColumnName("highest_item_level"); + + b.PrimitiveCollection>("KnownSpells") + .HasColumnType("integer[]") + .HasColumnName("known_spells"); + + b.Property("Level") + .HasColumnType("smallint") + .HasColumnName("level"); + + b.Property("LevelXp") + .HasColumnType("integer") + .HasColumnName("level_xp"); + + b.Property>("MythicPlus") + .HasColumnType("jsonb") + .HasColumnName("mythic_plus"); + + b.Property("MythicPlusScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("mythic_plus_scanned_at"); + + b.Property>>("MythicPlusSeasons") + .HasColumnType("jsonb") + .HasColumnName("mythic_plus_seasons"); + + b.Property>>("MythicPlusWeeks") + .HasColumnType("jsonb") + .HasColumnName("mythic_plus_weeks"); + + b.Property>("Paragons") + .HasColumnType("jsonb") + .HasColumnName("paragons"); + + b.Property>>("PatronOrders") + .HasColumnType("jsonb") + .HasColumnName("patron_orders"); + + b.Property("PatronOrdersScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("patron_orders_scanned_at"); + + b.Property>>("ProfessionCooldowns") + .HasColumnType("jsonb") + .HasColumnName("profession_cooldowns"); + + b.Property>>("ProfessionTraits") + .HasColumnType("jsonb") + .HasColumnName("profession_traits"); + + b.Property>("Professions") + .HasColumnType("jsonb") + .HasColumnName("professions"); + + b.Property>("Reputations") + .HasColumnType("jsonb") + .HasColumnName("reputations"); + + b.Property("ReputationsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reputations_scanned_at"); + + b.Property("WeeklyReset") + .HasColumnType("timestamp with time zone") + .HasColumnName("weekly_reset"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_data"); + + b.ToTable("player_character_addon_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonMounts", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("Mounts") + .HasColumnType("integer[]") + .HasColumnName("mounts"); + + b.Property("ScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_mounts"); + + b.ToTable("player_character_addon_mounts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonQuests", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CallingsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("callings_scanned_at"); + + b.PrimitiveCollection>("CompletedQuests") + .HasColumnType("integer[]") + .HasColumnName("completed_quests"); + + b.Property("CompletedQuestsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("completed_quests_scanned_at"); + + b.Property("CompressedCompletedIds") + .HasColumnType("bytea") + .HasColumnName("compressed_completed_ids"); + + b.Property>>>("Dailies") + .HasColumnType("jsonb") + .HasColumnName("dailies"); + + b.Property>>("GoldWorldQuests") + .HasColumnType("jsonb") + .HasColumnName("gold_world_quests"); + + b.Property>("ProgressQuests") + .HasColumnType("jsonb") + .HasColumnName("progress_quests"); + + b.Property("QuestsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("quests_scanned_at"); + + b.Property("WorldQuestsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("world_quests_scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_quests"); + + b.ToTable("player_character_addon_quests", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterConfiguration", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("BackgroundBrightness") + .HasColumnType("smallint") + .HasColumnName("background_brightness"); + + b.Property("BackgroundId") + .HasColumnType("smallint") + .HasColumnName("background_id"); + + b.Property("BackgroundSaturation") + .HasColumnType("smallint") + .HasColumnName("background_saturation"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_configuration"); + + b.ToTable("player_character_configuration", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterEquippedItems", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Items") + .HasColumnType("jsonb") + .HasColumnName("items"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_equipped_items"); + + b.ToTable("player_character_equipped_items", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("smallint[]") + .HasColumnName("bonus_ids"); + + b.Property("Bound") + .HasColumnType("boolean") + .HasColumnName("bound"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("ContainerId") + .HasColumnType("smallint") + .HasColumnName("container_id"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CraftedQuality") + .HasColumnType("smallint") + .HasColumnName("crafted_quality"); + + b.Property("EnchantId") + .HasColumnType("smallint") + .HasColumnName("enchant_id"); + + b.PrimitiveCollection>("Gems") + .HasColumnType("integer[]") + .HasColumnName("gems"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property("Location") + .HasColumnType("smallint") + .HasColumnName("location"); + + b.Property>("Modifiers") + .HasColumnType("jsonb") + .HasColumnName("modifiers"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("Slot") + .HasColumnType("smallint") + .HasColumnName("slot"); + + b.Property("SuffixId") + .HasColumnType("smallint") + .HasColumnName("suffix_id"); + + b.HasKey("Id") + .HasName("pk_player_character_item"); + + b.HasIndex("CharacterId", "Slot") + .HasDatabaseName("ix_player_character_item_character_id_slot"); + + b.HasIndex("CharacterId", "ItemId", "Location") + .HasDatabaseName("ix_player_character_item_character_id_item_id_location"); + + b.ToTable("player_character_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterLockouts", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("LastUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_updated"); + + b.Property>("Lockouts") + .HasColumnType("jsonb") + .HasColumnName("lockouts"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_lockouts"); + + b.ToTable("player_character_lockouts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMedia", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("AvatarUrl") + .HasColumnType("text") + .HasColumnName("avatar_url"); + + b.Property("InsetUrl") + .HasColumnType("text") + .HasColumnName("inset_url"); + + b.Property("MainRawUrl") + .HasColumnType("text") + .HasColumnName("main_raw_url"); + + b.Property("MainUrl") + .HasColumnType("text") + .HasColumnName("main_url"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_media"); + + b.ToTable("player_character_media", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMounts", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("Mounts") + .HasColumnType("integer[]") + .HasColumnName("mounts"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_mounts"); + + b.ToTable("player_character_mounts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlus", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CurrentPeriodId") + .HasColumnType("integer") + .HasColumnName("current_period_id"); + + b.Property>("PeriodRuns") + .HasColumnType("jsonb") + .HasColumnName("period_runs"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_mythic_plus"); + + b.ToTable("player_character_mythic_plus", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusAddon", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Maps") + .HasColumnType("jsonb") + .HasColumnName("maps"); + + b.Property("Season") + .HasColumnType("integer") + .HasColumnName("season"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_mythic_plus_addon"); + + b.ToTable("player_character_mythic_plus_addon", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusSeason", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Season") + .HasColumnType("integer") + .HasColumnName("season"); + + b.Property("Rating") + .HasColumnType("double precision") + .HasColumnName("rating"); + + b.Property>("Runs") + .HasColumnType("jsonb") + .HasColumnName("runs"); + + b.HasKey("CharacterId", "Season") + .HasName("pk_player_character_mythic_plus_season"); + + b.ToTable("player_character_mythic_plus_season", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterProfessions", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("ProfessionSpecializations") + .HasColumnType("jsonb") + .HasColumnName("profession_specializations"); + + b.Property>>("Professions") + .HasColumnType("jsonb") + .HasColumnName("professions"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_professions"); + + b.ToTable("player_character_professions", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterQuests", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("CompletedIds") + .HasColumnType("integer[]") + .HasColumnName("completed_ids"); + + b.Property("CompressedCompletedIds") + .HasColumnType("bytea") + .HasColumnName("compressed_completed_ids"); + + b.Property("ScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_quests"); + + b.ToTable("player_character_quests", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterRaiderIo", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Seasons") + .HasColumnType("jsonb") + .HasColumnName("seasons"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_raider_io"); + + b.ToTable("player_character_raider_io", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterReputations", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("ExtraReputationIds") + .HasColumnType("integer[]") + .HasColumnName("extra_reputation_ids"); + + b.PrimitiveCollection>("ExtraReputationValues") + .HasColumnType("integer[]") + .HasColumnName("extra_reputation_values"); + + b.Property>("Paragons") + .HasColumnType("jsonb") + .HasColumnName("paragons"); + + b.PrimitiveCollection>("ReputationIds") + .HasColumnType("integer[]") + .HasColumnName("reputation_ids"); + + b.PrimitiveCollection>("ReputationValues") + .HasColumnType("integer[]") + .HasColumnName("reputation_values"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_reputations"); + + b.ToTable("player_character_reputations", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterShadowlands", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("ConduitIds") + .HasColumnType("integer[]") + .HasColumnName("conduit_ids"); + + b.PrimitiveCollection>("ConduitRanks") + .HasColumnType("integer[]") + .HasColumnName("conduit_ranks"); + + b.Property("CovenantId") + .HasColumnType("integer") + .HasColumnName("covenant_id"); + + b.Property>("Covenants") + .HasColumnType("jsonb") + .HasColumnName("covenants"); + + b.Property("RenownLevel") + .HasColumnType("integer") + .HasColumnName("renown_level"); + + b.Property("SoulbindId") + .HasColumnType("integer") + .HasColumnName("soulbind_id"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_shadowlands"); + + b.ToTable("player_character_shadowlands", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterSpecializations", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Specializations") + .HasColumnType("jsonb") + .HasColumnName("specializations"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_specializations"); + + b.ToTable("player_character_specializations", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStatistics", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("StatisticDescriptions") + .HasColumnType("text[]") + .HasColumnName("statistic_descriptions"); + + b.PrimitiveCollection>("StatisticIds") + .HasColumnType("integer[]") + .HasColumnName("statistic_ids"); + + b.PrimitiveCollection>("StatisticQuantities") + .HasColumnType("integer[]") + .HasColumnName("statistic_quantities"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_statistics"); + + b.ToTable("player_character_statistics", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStats", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Basic") + .HasColumnType("jsonb") + .HasColumnName("basic"); + + b.Property>("Misc") + .HasColumnType("jsonb") + .HasColumnName("misc"); + + b.Property>("Rating") + .HasColumnType("jsonb") + .HasColumnName("rating"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_stats"); + + b.ToTable("player_character_stats", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterTransmog", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("IllusionIds") + .HasColumnType("integer[]") + .HasColumnName("illusion_ids"); + + b.PrimitiveCollection>("TransmogIds") + .HasColumnType("integer[]") + .HasColumnName("transmog_ids"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_transmog"); + + b.ToTable("player_character_transmog", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterWeekly", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("DelveGilded") + .HasColumnType("smallint") + .HasColumnName("delve_gilded"); + + b.PrimitiveCollection>("DelveLevels") + .HasColumnType("integer[]") + .HasColumnName("delve_levels"); + + b.PrimitiveCollection>("DelveMaps") + .HasColumnType("text[]") + .HasColumnName("delve_maps"); + + b.Property("DelveWeek") + .HasColumnType("integer") + .HasColumnName("delve_week"); + + b.Property("KeystoneDungeon") + .HasColumnType("integer") + .HasColumnName("keystone_dungeon"); + + b.Property("KeystoneLevel") + .HasColumnType("integer") + .HasColumnName("keystone_level"); + + b.Property("KeystoneScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("keystone_scanned_at"); + + b.Property>("Torghast") + .HasColumnType("jsonb") + .HasColumnName("torghast"); + + b.Property("TorghastScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("torghast_scanned_at"); + + b.Property("Vault") + .HasColumnType("jsonb") + .HasColumnName("vault"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_weekly"); + + b.ToTable("player_character_weekly", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuild", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property>("Tabs") + .HasColumnType("jsonb") + .HasColumnName("tabs"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_player_guild"); + + b.HasIndex("UserId", "RealmId", "Name") + .IsUnique() + .HasDatabaseName("ix_player_guild_user_id_realm_id_name"); + + b.ToTable("player_guild", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuildItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("smallint[]") + .HasColumnName("bonus_ids"); + + b.Property("Bound") + .HasColumnType("boolean") + .HasColumnName("bound"); + + b.Property("ContainerId") + .HasColumnType("smallint") + .HasColumnName("container_id"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CraftedQuality") + .HasColumnType("smallint") + .HasColumnName("crafted_quality"); + + b.Property("EnchantId") + .HasColumnType("smallint") + .HasColumnName("enchant_id"); + + b.PrimitiveCollection>("Gems") + .HasColumnType("integer[]") + .HasColumnName("gems"); + + b.Property("GuildId") + .HasColumnType("integer") + .HasColumnName("guild_id"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property>("Modifiers") + .HasColumnType("jsonb") + .HasColumnName("modifiers"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("Slot") + .HasColumnType("smallint") + .HasColumnName("slot"); + + b.Property("SuffixId") + .HasColumnType("smallint") + .HasColumnName("suffix_id"); + + b.HasKey("Id") + .HasName("pk_player_guild_item"); + + b.HasIndex("GuildId", "ItemId") + .HasDatabaseName("ix_player_guild_item_guild_id_item_id"); + + b.ToTable("player_guild_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerWarbankItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("smallint[]") + .HasColumnName("bonus_ids"); + + b.Property("Bound") + .HasColumnType("boolean") + .HasColumnName("bound"); + + b.Property("ContainerId") + .HasColumnType("smallint") + .HasColumnName("container_id"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CraftedQuality") + .HasColumnType("smallint") + .HasColumnName("crafted_quality"); + + b.Property("EnchantId") + .HasColumnType("smallint") + .HasColumnName("enchant_id"); + + b.PrimitiveCollection>("Gems") + .HasColumnType("integer[]") + .HasColumnName("gems"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property>("Modifiers") + .HasColumnType("jsonb") + .HasColumnName("modifiers"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Slot") + .HasColumnType("smallint") + .HasColumnName("slot"); + + b.Property("SuffixId") + .HasColumnType("smallint") + .HasColumnName("suffix_id"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_player_warbank_item"); + + b.HasIndex("UserId", "ItemId") + .HasDatabaseName("ix_player_warbank_item_user_id_item_id"); + + b.ToTable("player_warbank_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.AccountTransmogQuery", b => + { + b.PrimitiveCollection>("IllusionIds") + .HasColumnType("integer[]") + .HasColumnName("illusion_ids"); + + b.PrimitiveCollection>("TransmogIds") + .HasColumnType("integer[]") + .HasColumnName("transmog_ids"); + + b.ToTable("AccountTransmogQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.AchievementCriteriaQuery", b => + { + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CriteriaId") + .HasColumnType("integer") + .HasColumnName("criteria_id"); + + b.ToTable("AchievementCriteriaQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.ActiveConnectedRealmQuery", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.ToTable("ActiveConnectedRealmQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.AuctionBrowseQuery", b => + { + b.Property("GroupKey") + .HasColumnType("text") + .HasColumnName("group_key"); + + b.Property("LowestBuyoutPrice") + .HasColumnType("bigint") + .HasColumnName("lowest_buyout_price"); + + b.Property("TotalQuantity") + .HasColumnType("bigint") + .HasColumnName("total_quantity"); + + b.ToTable("AuctionBrowseQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.CompletedAchievementsQuery", b => + { + b.Property("AchievementId") + .HasColumnType("integer") + .HasColumnName("achievement_id"); + + b.Property("Timestamp") + .HasColumnType("integer") + .HasColumnName("timestamp"); + + b.ToTable("CompletedAchievementsQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.LatestPlayerAccountGoldSnapshotQuery", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.ToTable("LatestPlayerAccountGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.LatestUserGoldSnapshotQuery", b => + { + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("LatestUserGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.MountQuery", b => + { + b.PrimitiveCollection>("AddonMounts") + .HasColumnType("integer[]") + .HasColumnName("addon_mounts"); + + b.PrimitiveCollection>("Mounts") + .HasColumnType("integer[]") + .HasColumnName("mounts"); + + b.ToTable("MountQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.PlayerAccountGoldSnapshotQuery", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property("TotalGold") + .HasColumnType("integer") + .HasColumnName("total_gold"); + + b.ToTable("PlayerAccountGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.SchedulerCharacterQuery", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CharacterName") + .HasColumnType("text") + .HasColumnName("character_name"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("LastApiModified") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_modified"); + + b.Property("RealmSlug") + .HasColumnType("text") + .HasColumnName("realm_slug"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("SchedulerCharacterQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.SchedulerUserQuery", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("SchedulerUserQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.StatisticsQuery", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Quantity") + .HasColumnType("integer") + .HasColumnName("quantity"); + + b.Property("StatisticId") + .HasColumnType("integer") + .HasColumnName("statistic_id"); + + b.ToTable("StatisticsQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.UserGoldSnapshotQuery", b => + { + b.Property("TotalGold") + .HasColumnType("integer") + .HasColumnName("total_gold"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("UserGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.UserLeaderboardQuery", b => + { + b.Property("AppearanceIdCount") + .HasColumnType("integer") + .HasColumnName("appearance_id_count"); + + b.Property("AppearanceSourceCount") + .HasColumnType("integer") + .HasColumnName("appearance_source_count"); + + b.Property("CompletedQuestCount") + .HasColumnType("integer") + .HasColumnName("completed_quest_count"); + + b.Property("IllusionCount") + .HasColumnType("smallint") + .HasColumnName("illusion_count"); + + b.Property("MountCount") + .HasColumnType("smallint") + .HasColumnName("mount_count"); + + b.Property("ToyCount") + .HasColumnType("smallint") + .HasColumnName("toy_count"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("UserLeaderboardQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.QueuedJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .HasColumnType("text") + .HasColumnName("data"); + + b.Property("DataHash") + .HasColumnType("text") + .HasColumnName("data_hash"); + + b.Property("Failures") + .HasColumnType("smallint") + .HasColumnName("failures"); + + b.Property("Priority") + .HasColumnType("smallint") + .HasColumnName("priority"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("started_at"); + + b.Property("Type") + .HasColumnType("smallint") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_queued_job"); + + b.HasIndex("Priority") + .HasDatabaseName("ix_queued_job_priority") + .HasFilter("started_at IS NULL"); + + b.HasIndex("Priority", "Type", "DataHash") + .IsUnique() + .HasDatabaseName("ix_queued_job_priority_type_data_hash"); + + b.ToTable("queued_job", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.Team", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DefaultRealmId") + .HasColumnType("integer") + .HasColumnName("default_realm_id"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Guid") + .HasColumnType("uuid") + .HasColumnName("guid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_team"); + + b.HasIndex("Guid") + .IsUnique() + .HasDatabaseName("ix_team_guid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_team_user_id"); + + b.ToTable("team", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.TeamCharacter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("PrimaryRole") + .HasColumnType("smallint") + .HasColumnName("primary_role"); + + b.Property("SecondaryRole") + .HasColumnType("smallint") + .HasColumnName("secondary_role"); + + b.Property("TeamId") + .HasColumnType("integer") + .HasColumnName("team_id"); + + b.HasKey("Id") + .HasName("pk_team_character"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_team_character_character_id"); + + b.HasIndex("TeamId") + .HasDatabaseName("ix_team_character_team_id"); + + b.ToTable("team_character", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserAddonData", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("WarbankCopper") + .HasColumnType("bigint") + .HasColumnName("warbank_copper"); + + b.Property("WarbankGoldUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("warbank_gold_updated_at"); + + b.Property("WarbankUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("warbank_updated_at"); + + b.HasKey("UserId") + .HasName("pk_user_addon_data"); + + b.ToTable("user_addon_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserBulkData", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property>("Heirlooms") + .HasColumnType("jsonb") + .HasColumnName("heirlooms"); + + b.Property("HeirloomsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("heirlooms_updated_at"); + + b.PrimitiveCollection>("MountIds") + .HasColumnType("smallint[]") + .HasColumnName("mount_ids"); + + b.Property("MountsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("mounts_updated_at"); + + b.Property>("Pets") + .HasColumnType("jsonb") + .HasColumnName("pets"); + + b.Property("PetsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("pets_updated_at"); + + b.PrimitiveCollection>("ToyIds") + .HasColumnType("smallint[]") + .HasColumnName("toy_ids"); + + b.Property("ToysUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("toys_updated_at"); + + b.PrimitiveCollection>("TransmogIds") + .HasColumnType("integer[]") + .HasColumnName("transmog_ids"); + + b.Property("TransmogsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("transmogs_updated_at"); + + b.HasKey("UserId") + .HasName("pk_user_bulk_data"); + + b.ToTable("user_bulk_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserCache", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.PrimitiveCollection>("AppearanceIds") + .HasColumnType("integer[]") + .HasColumnName("appearance_ids"); + + b.PrimitiveCollection>("AppearanceSources") + .HasColumnType("text[]") + .HasColumnName("appearance_sources"); + + b.Property("CompletedQuests") + .HasColumnType("integer") + .HasColumnName("completed_quests"); + + b.PrimitiveCollection>("IllusionIds") + .HasColumnType("smallint[]") + .HasColumnName("illusion_ids"); + + b.PrimitiveCollection>("MountIds") + .HasColumnType("smallint[]") + .HasColumnName("mount_ids"); + + b.Property("MountsUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("mounts_updated"); + + b.PrimitiveCollection>("ToyIds") + .HasColumnType("smallint[]") + .HasColumnName("toy_ids"); + + b.Property("ToysUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("toys_updated"); + + b.Property("TransmogUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("transmog_updated"); + + b.HasKey("UserId") + .HasName("pk_user_cache"); + + b.ToTable("user_cache", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserGoldSnapshot", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_gold_snapshot"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_gold_snapshot_user_id"); + + b.ToTable("user_gold_snapshot", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserLeaderboardSnapshot", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("Date") + .HasColumnType("date") + .HasColumnName("date"); + + b.Property("AchievementPointsAlliance") + .HasColumnType("integer") + .HasColumnName("achievement_points_alliance"); + + b.Property("AchievementPointsHorde") + .HasColumnType("integer") + .HasColumnName("achievement_points_horde"); + + b.Property("AchievementPointsOverall") + .HasColumnType("integer") + .HasColumnName("achievement_points_overall"); + + b.Property("AppearanceIdCount") + .HasColumnType("integer") + .HasColumnName("appearance_id_count"); + + b.Property("AppearanceSourceCount") + .HasColumnType("integer") + .HasColumnName("appearance_source_count"); + + b.Property("CompletedQuestCount") + .HasColumnType("integer") + .HasColumnName("completed_quest_count"); + + b.Property("HeirloomCount") + .HasColumnType("smallint") + .HasColumnName("heirloom_count"); + + b.Property("HeirloomLevels") + .HasColumnType("smallint") + .HasColumnName("heirloom_levels"); + + b.Property("IllusionCount") + .HasColumnType("smallint") + .HasColumnName("illusion_count"); + + b.Property("MountCount") + .HasColumnType("smallint") + .HasColumnName("mount_count"); + + b.Property("PetCount") + .HasColumnType("smallint") + .HasColumnName("pet_count"); + + b.Property("RecipeCount") + .HasColumnType("smallint") + .HasColumnName("recipe_count"); + + b.Property("ReputationCount") + .HasColumnType("smallint") + .HasColumnName("reputation_count"); + + b.Property("TitleCount") + .HasColumnType("smallint") + .HasColumnName("title_count"); + + b.Property("ToyCount") + .HasColumnType("smallint") + .HasColumnName("toy_count"); + + b.HasKey("UserId", "Date") + .HasName("pk_user_leaderboard_snapshot"); + + b.HasIndex("UserId", "Date") + .IsDescending(false, true) + .HasDatabaseName("ix_user_leaderboard_snapshot_user_id_date"); + + b.ToTable("user_leaderboard_snapshot", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.WorldQuestAggregate", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ZoneId") + .HasColumnType("integer") + .HasColumnName("zone_id"); + + b.Property("QuestId") + .HasColumnType("integer") + .HasColumnName("quest_id"); + + b.Property("JsonData") + .HasColumnType("text") + .HasColumnName("json_data"); + + b.HasKey("Region", "ZoneId", "QuestId") + .HasName("pk_world_quest_aggregate"); + + b.ToTable("world_quest_aggregate", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.WorldQuestReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Class") + .HasColumnType("smallint") + .HasColumnName("class"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.Property("Location") + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("QuestId") + .HasColumnType("integer") + .HasColumnName("quest_id"); + + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ReportedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reported_at"); + + b.Property>("Rewards") + .HasColumnType("jsonb") + .HasColumnName("rewards"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("ZoneId") + .HasColumnType("integer") + .HasColumnName("zone_id"); + + b.HasKey("Id") + .HasName("pk_world_quest_report"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_world_quest_report_user_id"); + + b.HasIndex("Region", "ExpiresAt") + .IsDescending(false, true) + .HasDatabaseName("ix_world_quest_report_region_expires_at"); + + b.ToTable("world_quest_report", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuction", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("AuctionId") + .HasColumnType("integer") + .HasColumnName("auction_id"); + + b.Property("AppearanceId") + .HasColumnType("integer") + .HasColumnName("appearance_id"); + + b.Property("AppearanceSource") + .HasColumnType("text") + .HasColumnName("appearance_source"); + + b.Property("BidPrice") + .HasColumnType("bigint") + .HasColumnName("bid_price"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("integer[]") + .HasColumnName("bonus_ids"); + + b.Property("BuyoutPrice") + .HasColumnType("bigint") + .HasColumnName("buyout_price"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("GroupKey") + .HasColumnType("text") + .HasColumnName("group_key"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.PrimitiveCollection>("ModifierTypes") + .HasColumnType("smallint[]") + .HasColumnName("modifier_types"); + + b.PrimitiveCollection>("ModifierValues") + .HasColumnType("integer[]") + .HasColumnName("modifier_values"); + + b.Property("PetBreedId") + .HasColumnType("smallint") + .HasColumnName("pet_breed_id"); + + b.Property("PetLevel") + .HasColumnType("smallint") + .HasColumnName("pet_level"); + + b.Property("PetQuality") + .HasColumnType("smallint") + .HasColumnName("pet_quality"); + + b.Property("PetSpeciesId") + .HasColumnType("smallint") + .HasColumnName("pet_species_id"); + + b.Property("Quantity") + .HasColumnType("integer") + .HasColumnName("quantity"); + + b.Property("TimeLeft") + .HasColumnType("smallint") + .HasColumnName("time_left"); + + b.HasKey("ConnectedRealmId", "AuctionId") + .HasName("pk_wow_auction"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_wow_auction_item_id"); + + b.HasIndex("PetSpeciesId") + .HasDatabaseName("ix_wow_auction_pet_species_id"); + + b.HasIndex("AppearanceId", "BuyoutPrice") + .HasDatabaseName("ix_wow_auction_appearance_id_buyout_price") + .HasFilter("appearance_id IS NOT NULL"); + + b.HasIndex("AppearanceSource", "BuyoutPrice") + .HasDatabaseName("ix_wow_auction_appearance_source_buyout_price") + .HasFilter("appearance_source IS NOT NULL"); + + b.ToTable("wow_auction", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCheapestByAppearanceId", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("AppearanceId") + .HasColumnType("integer") + .HasColumnName("appearance_id"); + + b.Property("AuctionId") + .HasColumnType("integer") + .HasColumnName("auction_id"); + + b.HasKey("ConnectedRealmId", "AppearanceId") + .HasName("pk_wow_auction_cheapest_by_appearance_id"); + + b.ToTable("wow_auction_cheapest_by_appearance_id", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCheapestByAppearanceSource", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("AppearanceSource") + .HasColumnType("text") + .HasColumnName("appearance_source"); + + b.Property("AuctionId") + .HasColumnType("integer") + .HasColumnName("auction_id"); + + b.HasKey("ConnectedRealmId", "AppearanceSource") + .HasName("pk_wow_auction_cheapest_by_appearance_source"); + + b.ToTable("wow_auction_cheapest_by_appearance_source", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCommodityDaily", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Date") + .HasColumnType("date") + .HasColumnName("date"); + + b.PrimitiveCollection>("AvgData") + .HasColumnType("integer[]") + .HasColumnName("avg_data"); + + b.Property("ListedMax") + .HasColumnType("integer") + .HasColumnName("listed_max"); + + b.Property("ListedMin") + .HasColumnType("integer") + .HasColumnName("listed_min"); + + b.PrimitiveCollection>("MaxData") + .HasColumnType("integer[]") + .HasColumnName("max_data"); + + b.PrimitiveCollection>("MinData") + .HasColumnType("integer[]") + .HasColumnName("min_data"); + + b.HasKey("Region", "ItemId", "Date") + .HasName("pk_wow_auction_commodity_daily"); + + b.ToTable("wow_auction_commodity_daily", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCommodityHourly", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.PrimitiveCollection>("Data") + .HasColumnType("integer[]") + .HasColumnName("data"); + + b.Property("Listed") + .HasColumnType("integer") + .HasColumnName("listed"); + + b.HasKey("Region", "ItemId", "Timestamp") + .HasName("pk_wow_auction_commodity_hourly"); + + b.ToTable("wow_auction_commodity_hourly", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCampaign", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.PrimitiveCollection>("QuestLineIds") + .HasColumnType("integer[]") + .HasColumnName("quest_line_ids"); + + b.HasKey("Id") + .HasName("pk_wow_campaign"); + + b.ToTable("wow_campaign", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowChallengeDungeon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("MapId") + .HasColumnType("smallint") + .HasColumnName("map_id"); + + b.PrimitiveCollection>("TimerBreakpoints") + .HasColumnType("smallint[]") + .HasColumnName("timer_breakpoints"); + + b.HasKey("Id") + .HasName("pk_wow_challenge_dungeon"); + + b.ToTable("wow_challenge_dungeon", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCharacterClass", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArmorMask") + .HasColumnType("smallint") + .HasColumnName("armor_mask"); + + b.Property("RolesMask") + .HasColumnType("smallint") + .HasColumnName("roles_mask"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.HasKey("Id") + .HasName("pk_wow_character_class"); + + b.ToTable("wow_character_class", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCharacterRace", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Bit") + .HasColumnType("smallint") + .HasColumnName("bit"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.HasKey("Id") + .HasName("pk_wow_character_race"); + + b.ToTable("wow_character_race", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCharacterSpecialization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.Property("Order") + .HasColumnType("smallint") + .HasColumnName("order"); + + b.Property("PrimaryStat") + .HasColumnType("smallint") + .HasColumnName("primary_stat"); + + b.Property("Role") + .HasColumnType("smallint") + .HasColumnName("role"); + + b.HasKey("Id") + .HasName("pk_wow_character_specialization"); + + b.ToTable("wow_character_specialization", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("smallint") + .HasColumnName("category_id"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("MaxPerWeek") + .HasColumnType("integer") + .HasColumnName("max_per_week"); + + b.Property("MaxTotal") + .HasColumnType("integer") + .HasColumnName("max_total"); + + b.Property("RechargeAmount") + .HasColumnType("smallint") + .HasColumnName("recharge_amount"); + + b.Property("RechargeInterval") + .HasColumnType("bigint") + .HasColumnName("recharge_interval"); + + b.Property("TransferPercent") + .HasColumnType("smallint") + .HasColumnName("transfer_percent"); + + b.HasKey("Id") + .HasName("pk_wow_currency"); + + b.ToTable("wow_currency", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCurrencyCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.HasKey("Id") + .HasName("pk_wow_currency_category"); + + b.ToTable("wow_currency_category", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowDecor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Type") + .HasColumnType("smallint") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_wow_decor"); + + b.ToTable("wow_decor", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowHoliday", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DescriptionId") + .HasColumnType("smallint") + .HasColumnName("description_id"); + + b.PrimitiveCollection>("Durations") + .HasColumnType("smallint[]") + .HasColumnName("durations"); + + b.Property("FilterType") + .HasColumnType("smallint") + .HasColumnName("filter_type"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("Looping") + .HasColumnType("smallint") + .HasColumnName("looping"); + + b.Property("NameId") + .HasColumnType("smallint") + .HasColumnName("name_id"); + + b.Property("Priority") + .HasColumnType("smallint") + .HasColumnName("priority"); + + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.PrimitiveCollection>("StartDates") + .HasColumnType("timestamp with time zone[]") + .HasColumnName("start_dates"); + + b.HasKey("Id") + .HasName("pk_wow_holiday"); + + b.ToTable("wow_holiday", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.Property("ClassMask") + .HasColumnType("integer") + .HasColumnName("class_mask"); + + b.PrimitiveCollection("CompletesQuestIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("completes_quest_ids"); + + b.Property("ContainerSlots") + .HasColumnType("smallint") + .HasColumnName("container_slots"); + + b.Property("CraftingQuality") + .HasColumnType("smallint") + .HasColumnName("crafting_quality"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("InventoryType") + .HasColumnType("smallint") + .HasColumnName("inventory_type"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property("LimitCategory") + .HasColumnType("smallint") + .HasColumnName("limit_category"); + + b.Property("OppositeFactionId") + .HasColumnType("integer") + .HasColumnName("opposite_faction_id"); + + b.Property("PrimaryStat") + .HasColumnType("smallint") + .HasColumnName("primary_stat"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("RaceMask") + .HasColumnType("bigint") + .HasColumnName("race_mask"); + + b.Property("RequiredAbility") + .HasColumnType("integer") + .HasColumnName("required_ability"); + + b.Property("RequiredLevel") + .HasColumnType("smallint") + .HasColumnName("required_level"); + + b.Property("RequiredSkill") + .HasColumnType("smallint") + .HasColumnName("required_skill"); + + b.Property("RequiredSkillRank") + .HasColumnType("smallint") + .HasColumnName("required_skill_rank"); + + b.PrimitiveCollection("Sockets") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("smallint[]") + .HasDefaultValue(new short[0]) + .HasColumnName("sockets"); + + b.Property("Stackable") + .HasColumnType("integer") + .HasColumnName("stackable"); + + b.Property("SubclassId") + .HasColumnType("smallint") + .HasColumnName("subclass_id"); + + b.PrimitiveCollection("TeachesDecorIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_decor_ids"); + + b.PrimitiveCollection("TeachesSpellIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_spell_ids"); + + b.PrimitiveCollection("TeachesTransmogIllusionIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_transmog_illusion_ids"); + + b.PrimitiveCollection("TeachesTransmogSetIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_transmog_set_ids"); + + b.Property("Unique") + .HasColumnType("smallint") + .HasColumnName("unique"); + + b.HasKey("Id") + .HasName("pk_wow_item"); + + b.ToTable("wow_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemBonus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BonusTypeFlags") + .HasColumnType("bigint") + .HasColumnName("bonus_type_flags"); + + b.Property>>("Bonuses") + .HasColumnType("jsonb") + .HasColumnName("bonuses"); + + b.HasKey("Id") + .HasName("pk_wow_item_bonus"); + + b.ToTable("wow_item_bonus", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemClass", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.HasKey("Id") + .HasName("pk_wow_item_class"); + + b.ToTable("wow_item_class", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemEffect", b => + { + b.Property("ItemXItemEffectId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("item_x_item_effect_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemXItemEffectId")); + + b.Property("Effect") + .HasColumnType("integer") + .HasColumnName("effect"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.PrimitiveCollection("Values") + .HasColumnType("integer[]") + .HasColumnName("values"); + + b.HasKey("ItemXItemEffectId") + .HasName("pk_wow_item_effect"); + + b.ToTable("wow_item_effect", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemEffectV2", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("item_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.PrimitiveCollection>("ItemEffectIds") + .HasColumnType("integer[]") + .HasColumnName("item_effect_ids"); + + b.Property>>("SpellEffects") + .HasColumnType("jsonb") + .HasColumnName("spell_effects"); + + b.HasKey("ItemId") + .HasName("pk_wow_item_effect_v2"); + + b.ToTable("wow_item_effect_v2", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemModifiedAppearance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AppearanceId") + .HasColumnType("integer") + .HasColumnName("appearance_id"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Modifier") + .HasColumnType("smallint") + .HasColumnName("modifier"); + + b.Property("Order") + .HasColumnType("smallint") + .HasColumnName("order"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.HasKey("Id") + .HasName("pk_wow_item_modified_appearance"); + + b.ToTable("wow_item_modified_appearance", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemSubclass", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuctionHouseSortOrder") + .HasColumnType("smallint") + .HasColumnName("auction_house_sort_order"); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.Property("SubclassId") + .HasColumnType("smallint") + .HasColumnName("subclass_id"); + + b.HasKey("Id") + .HasName("pk_wow_item_subclass"); + + b.ToTable("wow_item_subclass", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowJournalInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.Property("MapId") + .HasColumnType("smallint") + .HasColumnName("map_id"); + + b.HasKey("Id") + .HasName("pk_wow_journal_instance"); + + b.ToTable("wow_journal_instance", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowMount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.PrimitiveCollection>("ItemIds") + .HasColumnType("integer[]") + .HasColumnName("item_ids"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.Property("SpellId") + .HasColumnType("integer") + .HasColumnName("spell_id"); + + b.HasKey("Id") + .HasName("pk_wow_mount"); + + b.ToTable("wow_mount", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowMythicPlusSeason", b => + { + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.HasKey("Region", "Id") + .HasName("pk_wow_mythic_plus_season"); + + b.ToTable("wow_mythic_plus_season", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowPeriod", b => + { + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Ends") + .HasColumnType("timestamp with time zone") + .HasColumnName("ends"); + + b.Property("Starts") + .HasColumnType("timestamp with time zone") + .HasColumnName("starts"); + + b.HasKey("Region", "Id") + .HasName("pk_wow_period"); + + b.ToTable("wow_period", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowPet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatureId") + .HasColumnType("integer") + .HasColumnName("creature_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.PrimitiveCollection>("ItemIds") + .HasColumnType("integer[]") + .HasColumnName("item_ids"); + + b.Property("PetType") + .HasColumnType("smallint") + .HasColumnName("pet_type"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.Property("SpellId") + .HasColumnType("integer") + .HasColumnName("spell_id"); + + b.HasKey("Id") + .HasName("pk_wow_pet"); + + b.ToTable("wow_pet", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowProfessionRecipeItem", b => + { + b.Property("SkillLineAbilityId") + .HasColumnType("integer") + .HasColumnName("skill_line_ability_id"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("SkillLineId") + .HasColumnType("integer") + .HasColumnName("skill_line_id"); + + b.HasKey("SkillLineAbilityId", "ItemId") + .HasName("pk_wow_profession_recipe_item"); + + b.ToTable("wow_profession_recipe_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowQuest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AreaId") + .HasColumnType("integer") + .HasColumnName("area_id"); + + b.Property("CategoryId") + .HasColumnType("integer") + .HasColumnName("category_id"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("MaximumLevel") + .HasColumnType("smallint") + .HasColumnName("maximum_level"); + + b.Property("MinimumLevel") + .HasColumnType("smallint") + .HasColumnName("minimum_level"); + + b.HasKey("Id") + .HasName("pk_wow_quest"); + + b.ToTable("wow_quest", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowQuestLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.PrimitiveCollection>("QuestIds") + .HasColumnType("integer[]") + .HasColumnName("quest_ids"); + + b.HasKey("Id") + .HasName("pk_wow_quest_line"); + + b.ToTable("wow_quest_line", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowRealm", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("EnglishName") + .HasColumnType("text") + .HasColumnName("english_name"); + + b.Property("Locale") + .HasColumnType("text") + .HasColumnName("locale"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.HasKey("Id") + .HasName("pk_wow_realm"); + + b.ToTable("wow_realm", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowReputation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountWide") + .HasColumnType("boolean") + .HasColumnName("account_wide"); + + b.PrimitiveCollection>("BaseValues") + .HasColumnType("integer[]") + .HasColumnName("base_values"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.PrimitiveCollection>("MaxValues") + .HasColumnType("integer[]") + .HasColumnName("max_values"); + + b.Property("ParagonId") + .HasColumnType("smallint") + .HasColumnName("paragon_id"); + + b.Property("ParagonQuestId") + .HasColumnType("integer") + .HasColumnName("paragon_quest_id"); + + b.Property("ParagonThreshold") + .HasColumnType("integer") + .HasColumnName("paragon_threshold"); + + b.Property("ParentId") + .HasColumnType("smallint") + .HasColumnName("parent_id"); + + b.Property("RenownCurrencyId") + .HasColumnType("smallint") + .HasColumnName("renown_currency_id"); + + b.Property("TierId") + .HasColumnType("smallint") + .HasColumnName("tier_id"); + + b.HasKey("Id") + .HasName("pk_wow_reputation"); + + b.ToTable("wow_reputation", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowReputationTier", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.PrimitiveCollection("MinValues") + .HasColumnType("integer[]") + .HasColumnName("min_values"); + + b.HasKey("Id") + .HasName("pk_wow_reputation_tier"); + + b.ToTable("wow_reputation_tier", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowToy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.HasKey("Id") + .HasName("pk_wow_toy"); + + b.ToTable("wow_toy", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowTransmogSet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClassMask") + .HasColumnType("integer") + .HasColumnName("class_mask"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("GroupId") + .HasColumnType("smallint") + .HasColumnName("group_id"); + + b.PrimitiveCollection>("ItemModifiedAppearanceIds") + .HasColumnType("integer[]") + .HasColumnName("item_modified_appearance_ids"); + + b.Property("ItemNameDescriptionId") + .HasColumnType("integer") + .HasColumnName("item_name_description_id"); + + b.HasKey("Id") + .HasName("pk_wow_transmog_set"); + + b.ToTable("wow_transmog_set", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowWorldQuest", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.Property("MaxLevel") + .HasColumnType("smallint") + .HasColumnName("max_level"); + + b.Property("MinLevel") + .HasColumnType("smallint") + .HasColumnName("min_level"); + + b.PrimitiveCollection>("NeedQuestIds") + .HasColumnType("integer[]") + .HasColumnName("need_quest_ids"); + + b.Property("QuestInfoId") + .HasColumnType("smallint") + .HasColumnName("quest_info_id"); + + b.PrimitiveCollection>("SkipQuestIds") + .HasColumnType("integer[]") + .HasColumnName("skip_quest_ids"); + + b.HasKey("Id") + .HasName("pk_wow_world_quest"); + + b.ToTable("wow_world_quest", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_role_claims_asp_net_roles_role_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_claims_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_logins_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_roles_asp_net_roles_role_id"); + + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_roles_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_tokens_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.BackgroundImage", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", "Role") + .WithMany() + .HasForeignKey("RoleId") + .HasConstraintName("fk_background_image_roles_role_id"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.MiscReport", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_misc_report_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccount", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_player_account_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAchievements", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_achievements_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAddonData", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("AddonData") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountAddonData", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_addon_data_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountGoldSnapshot", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_gold_snapshot_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountHeirlooms", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Heirlooms") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountHeirlooms", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_heirlooms_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountMounts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Mounts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountMounts", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_mounts_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountPets", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Pets") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountPets", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_pets_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountToys", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Toys") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountToys", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_toys_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogIds", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("TransmogIds") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountTransmogIds", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_transmog_ids_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogSources", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("TransmogSources") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountTransmogSources", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_transmog_sources_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacter", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithMany("Characters") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_player_character_player_account_account_id"); + + b.HasOne("Wowthing.Lib.Models.Player.PlayerGuild", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .HasConstraintName("fk_player_character_player_guild_guild_id"); + + b.Navigation("Account"); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAchievements", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Achievements") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAchievements", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_achievements_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonAchievements", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonAchievements") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonAchievements", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_achievements_player_character_charac"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonData", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonData") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonData", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_data_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonMounts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonMounts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonMounts", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_mounts_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonQuests", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonQuests") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonQuests", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_quests_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterConfiguration", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Configuration") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterConfiguration", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_configuration_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterEquippedItems", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("EquippedItems") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterEquippedItems", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_equipped_items_player_character_character_"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterItem", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany("Items") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_item_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterLockouts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Lockouts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterLockouts", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_lockouts_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMedia", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Media") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMedia", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_media_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMounts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Mounts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMounts", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mounts_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlus", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("MythicPlus") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlus", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mythic_plus_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusAddon", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("MythicPlusAddon") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusAddon", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mythic_plus_addon_player_character_charact"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusSeason", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany("MythicPlusSeasons") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mythic_plus_season_player_character_charac"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterProfessions", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Professions") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterProfessions", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_professions_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterQuests", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Quests") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterQuests", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_quests_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterRaiderIo", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("RaiderIo") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterRaiderIo", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_raider_io_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterReputations", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Reputations") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterReputations", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_reputations_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterShadowlands", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Shadowlands") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterShadowlands", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_shadowlands_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterSpecializations", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Specializations") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterSpecializations", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_specializations_player_character_character"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStatistics", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_statistics_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStats", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Stats") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterStats", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_stats_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterTransmog", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Transmog") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterTransmog", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_transmog_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterWeekly", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Weekly") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterWeekly", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_weekly_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuild", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_guild_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuildItem", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerGuild", "Guild") + .WithMany("Items") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_guild_item_player_guild_guild_id"); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerWarbankItem", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_warbank_item_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.Team", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_team_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.TeamCharacter", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_team_character_player_character_character_id"); + + b.HasOne("Wowthing.Lib.Models.Team.Team", "Team") + .WithMany("Characters") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_team_character_team_team_id"); + + b.Navigation("Character"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserAddonData", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_addon_data_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserBulkData", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_bulk_data_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserCache", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_cache_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserGoldSnapshot", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_user_gold_snapshot_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserLeaderboardSnapshot", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_leaderboard_snapshot_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.WorldQuestReport", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_world_quest_report_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccount", b => + { + b.Navigation("AddonData"); + + b.Navigation("Characters"); + + b.Navigation("Heirlooms"); + + b.Navigation("Mounts"); + + b.Navigation("Pets"); + + b.Navigation("Toys"); + + b.Navigation("TransmogIds"); + + b.Navigation("TransmogSources"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacter", b => + { + b.Navigation("Achievements"); + + b.Navigation("AddonAchievements"); + + b.Navigation("AddonData"); + + b.Navigation("AddonMounts"); + + b.Navigation("AddonQuests"); + + b.Navigation("Configuration"); + + b.Navigation("EquippedItems"); + + b.Navigation("Items"); + + b.Navigation("Lockouts"); + + b.Navigation("Media"); + + b.Navigation("Mounts"); + + b.Navigation("MythicPlus"); + + b.Navigation("MythicPlusAddon"); + + b.Navigation("MythicPlusSeasons"); + + b.Navigation("Professions"); + + b.Navigation("Quests"); + + b.Navigation("RaiderIo"); + + b.Navigation("Reputations"); + + b.Navigation("Shadowlands"); + + b.Navigation("Specializations"); + + b.Navigation("Stats"); + + b.Navigation("Transmog"); + + b.Navigation("Weekly"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuild", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.Team", b => + { + b.Navigation("Characters"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/packages/csharp-lib/Migrations/20260704213450_Add_PlayerAccountAchievements.cs b/packages/csharp-lib/Migrations/20260704213450_Add_PlayerAccountAchievements.cs new file mode 100644 index 000000000..52d063a48 --- /dev/null +++ b/packages/csharp-lib/Migrations/20260704213450_Add_PlayerAccountAchievements.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Wowthing.Lib.Migrations +{ + /// + public partial class Add_PlayerAccountAchievements : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "player_account_achievements", + columns: table => new + { + account_id = table.Column(type: "integer", nullable: false), + compressed_achievement_ids = table.Column(type: "bytea", nullable: true), + achievement_timestamps = table.Column>(type: "integer[]", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_player_account_achievements", x => x.account_id); + table.ForeignKey( + name: "fk_player_account_achievements_player_account_account_id", + column: x => x.account_id, + principalTable: "player_account", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "player_account_achievements"); + } + } +} diff --git a/packages/csharp-lib/Migrations/20260704214654_Add_PlayerCharacterAchievements_CompressedCriteriaIds.Designer.cs b/packages/csharp-lib/Migrations/20260704214654_Add_PlayerCharacterAchievements_CompressedCriteriaIds.Designer.cs new file mode 100644 index 000000000..257a58bdf --- /dev/null +++ b/packages/csharp-lib/Migrations/20260704214654_Add_PlayerCharacterAchievements_CompressedCriteriaIds.Designer.cs @@ -0,0 +1,4550 @@ +// +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Wowthing.Lib.Contexts; +using Wowthing.Lib.Enums; +using Wowthing.Lib.Models; +using Wowthing.Lib.Models.Global; +using Wowthing.Lib.Models.Player; +using Wowthing.Lib.Models.Wow; + +#nullable disable + +namespace Wowthing.Lib.Migrations +{ + [DbContext(typeof(WowDbContext))] + [Migration("20260704214654_Add_PlayerCharacterAchievements_CompressedCriteriaIds")] + partial class Add_PlayerCharacterAchievements_CompressedCriteriaIds + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text") + .HasColumnName("concurrency_stamp"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("name"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("normalized_name"); + + b.HasKey("Id") + .HasName("pk_asp_net_roles"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("asp_net_roles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text") + .HasColumnName("claim_type"); + + b.Property("ClaimValue") + .HasColumnType("text") + .HasColumnName("claim_value"); + + b.Property("RoleId") + .HasColumnType("bigint") + .HasColumnName("role_id"); + + b.HasKey("Id") + .HasName("pk_asp_net_role_claims"); + + b.HasIndex("RoleId") + .HasDatabaseName("ix_asp_net_role_claims_role_id"); + + b.ToTable("asp_net_role_claims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text") + .HasColumnName("claim_type"); + + b.Property("ClaimValue") + .HasColumnType("text") + .HasColumnName("claim_value"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_asp_net_user_claims"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_asp_net_user_claims_user_id"); + + b.ToTable("asp_net_user_claims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text") + .HasColumnName("login_provider"); + + b.Property("ProviderKey") + .HasColumnType("text") + .HasColumnName("provider_key"); + + b.Property("ProviderDisplayName") + .HasColumnType("text") + .HasColumnName("provider_display_name"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("LoginProvider", "ProviderKey") + .HasName("pk_asp_net_user_logins"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_asp_net_user_logins_user_id"); + + b.ToTable("asp_net_user_logins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("RoleId") + .HasColumnType("bigint") + .HasColumnName("role_id"); + + b.HasKey("UserId", "RoleId") + .HasName("pk_asp_net_user_roles"); + + b.HasIndex("RoleId") + .HasDatabaseName("ix_asp_net_user_roles_role_id"); + + b.ToTable("asp_net_user_roles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("LoginProvider") + .HasColumnType("text") + .HasColumnName("login_provider"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Value") + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("UserId", "LoginProvider", "Name") + .HasName("pk_asp_net_user_tokens"); + + b.ToTable("asp_net_user_tokens", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccessFailedCount") + .HasColumnType("integer") + .HasColumnName("access_failed_count"); + + b.Property("ApiKey") + .HasColumnType("text") + .HasColumnName("api_key"); + + b.Property("CanUseSubdomain") + .HasColumnType("boolean") + .HasColumnName("can_use_subdomain"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text") + .HasColumnName("concurrency_stamp"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("email"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean") + .HasColumnName("email_confirmed"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("LastVisit") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_visit"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean") + .HasColumnName("lockout_enabled"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone") + .HasColumnName("lockout_end"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("normalized_email"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("normalized_user_name"); + + b.Property("PasswordHash") + .HasColumnType("text") + .HasColumnName("password_hash"); + + b.Property("PhoneNumber") + .HasColumnType("text") + .HasColumnName("phone_number"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean") + .HasColumnName("phone_number_confirmed"); + + b.Property("SecurityStamp") + .HasColumnType("text") + .HasColumnName("security_stamp"); + + b.Property("Settings") + .HasColumnType("jsonb") + .HasColumnName("settings"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean") + .HasColumnName("two_factor_enabled"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("pk_asp_net_users"); + + b.HasIndex("ApiKey") + .IsUnique() + .HasDatabaseName("ix_asp_net_users_api_key"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("asp_net_users", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("text") + .HasColumnName("action"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_audit_log"); + + b.ToTable("audit_log", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.BackgroundImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Attribution") + .HasColumnType("text") + .HasColumnName("attribution"); + + b.Property("DefaultBrightness") + .HasColumnType("smallint") + .HasColumnName("default_brightness"); + + b.Property("DefaultSaturate") + .HasColumnType("smallint") + .HasColumnName("default_saturate"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Filename") + .HasColumnType("text") + .HasColumnName("filename"); + + b.Property("RoleId") + .HasColumnType("bigint") + .HasColumnName("role_id"); + + b.HasKey("Id") + .HasName("pk_background_image"); + + b.HasIndex("RoleId") + .HasDatabaseName("ix_background_image_role_id"); + + b.ToTable("background_image", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Global.GlobalDailies", b => + { + b.Property("Expansion") + .HasColumnType("integer") + .HasColumnName("expansion"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.PrimitiveCollection>("QuestExpires") + .HasColumnType("integer[]") + .HasColumnName("quest_expires"); + + b.PrimitiveCollection>("QuestIds") + .HasColumnType("integer[]") + .HasColumnName("quest_ids"); + + b.Property>("QuestRewards") + .HasColumnType("jsonb") + .HasColumnName("quest_rewards"); + + b.HasKey("Expansion", "Region") + .HasName("pk_global_dailies"); + + b.ToTable("global_dailies", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Image", b => + { + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Format") + .HasColumnType("smallint") + .HasColumnName("format"); + + b.Property("Data") + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Sha256") + .HasColumnType("char(64)") + .HasColumnName("sha256"); + + b.HasKey("Type", "Id", "Format") + .HasName("pk_image"); + + b.HasIndex("Type", "Sha256", "Format") + .HasDatabaseName("ix_image_type_sha256_format"); + + b.ToTable("image", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.LanguageString", b => + { + b.Property("Language") + .HasColumnType("smallint") + .HasColumnName("language"); + + b.Property("Type") + .HasColumnType("smallint") + .HasColumnName("type"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("String") + .HasColumnType("text") + .HasColumnName("string"); + + b.HasKey("Language", "Type", "Id") + .HasName("pk_language_string"); + + b.HasIndex("String") + .HasDatabaseName("ix_language_string_string"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("String"), "gin"); + NpgsqlIndexBuilderExtensions.HasOperators(b.HasIndex("String"), new[] { "gin_trgm_ops" }); + + b.HasIndex("Language", "Type", "Id") + .HasDatabaseName("ix_language_string_language_type_id"); + + b.ToTable("language_string", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.MiscAggregate", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ReportType") + .HasColumnType("smallint") + .HasColumnName("report_type"); + + b.Property("JsonData") + .HasColumnType("text") + .HasColumnName("json_data"); + + b.HasKey("Region", "ReportType") + .HasName("pk_misc_aggregate"); + + b.ToTable("misc_aggregate", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.MiscReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)") + .HasColumnName("data"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ReportType") + .HasColumnType("smallint") + .HasColumnName("report_type"); + + b.Property("ReportedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reported_at"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_misc_report"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_misc_report_user_id"); + + b.HasIndex("ReportType", "Region", "ExpiresAt") + .IsDescending(false, false, true) + .HasDatabaseName("ix_misc_report_report_type_region_expires_at"); + + b.ToTable("misc_report", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("bigint") + .HasColumnName("account_id"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Tag") + .HasColumnType("text") + .HasColumnName("tag"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_player_account"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_player_account_user_id"); + + b.HasIndex("Region", "AccountId") + .IsUnique() + .HasDatabaseName("ix_player_account_region_account_id"); + + b.ToTable("player_account", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAchievements", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("AchievementTimestamps") + .HasColumnType("integer[]") + .HasColumnName("achievement_timestamps"); + + b.Property("CompressedAchievementIds") + .HasColumnType("bytea") + .HasColumnName("compressed_achievement_ids"); + + b.HasKey("AccountId") + .HasName("pk_player_account_achievements"); + + b.ToTable("player_account_achievements", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAddonData", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property>>("Decor") + .HasColumnType("jsonb") + .HasColumnName("decor"); + + b.Property("DecorScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("decor_scanned_at"); + + b.Property>("Heirlooms") + .HasColumnType("jsonb") + .HasColumnName("heirlooms"); + + b.Property("HonorCurrent") + .HasColumnType("smallint") + .HasColumnName("honor_current"); + + b.Property("HonorLevel") + .HasColumnType("smallint") + .HasColumnName("honor_level"); + + b.Property("HonorMax") + .HasColumnType("smallint") + .HasColumnName("honor_max"); + + b.PrimitiveCollection>("Illusions") + .HasColumnType("integer[]") + .HasColumnName("illusions"); + + b.PrimitiveCollection>("Quests") + .HasColumnType("integer[]") + .HasColumnName("quests"); + + b.Property>("Reputations") + .HasColumnType("jsonb") + .HasColumnName("reputations"); + + b.Property("ReputationsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reputations_scanned_at"); + + b.HasKey("AccountId") + .HasName("pk_player_account_addon_data"); + + b.ToTable("player_account_addon_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountGoldSnapshot", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_player_account_gold_snapshot"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_player_account_gold_snapshot_account_id"); + + b.ToTable("player_account_gold_snapshot", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountHeirlooms", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property>("Heirlooms") + .HasColumnType("jsonb") + .HasColumnName("heirlooms"); + + b.HasKey("AccountId") + .HasName("pk_player_account_heirlooms"); + + b.ToTable("player_account_heirlooms", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountMounts", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("MountIds") + .HasColumnType("integer[]") + .HasColumnName("mount_ids"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("AccountId") + .HasName("pk_player_account_mounts"); + + b.ToTable("player_account_mounts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountPets", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property>("Pets") + .HasColumnType("jsonb") + .HasColumnName("pets"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("AccountId") + .HasName("pk_player_account_pets"); + + b.ToTable("player_account_pets", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountToys", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("ToyIds") + .HasColumnType("integer[]") + .HasColumnName("toy_ids"); + + b.HasKey("AccountId") + .HasName("pk_player_account_toys"); + + b.ToTable("player_account_toys", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogIds", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("Ids") + .HasColumnType("integer[]") + .HasColumnName("ids"); + + b.HasKey("AccountId") + .HasName("pk_player_account_transmog_ids"); + + b.ToTable("player_account_transmog_ids", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogSources", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("Sources") + .HasColumnType("text[]") + .HasColumnName("sources"); + + b.HasKey("AccountId") + .HasName("pk_player_account_transmog_sources"); + + b.ToTable("player_account_transmog_sources", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("ActiveSpecId") + .HasColumnType("integer") + .HasColumnName("active_spec_id"); + + b.Property("ActiveTitleId") + .HasColumnType("integer") + .HasColumnName("active_title_id"); + + b.Property("AverageItemLevel") + .HasColumnType("integer") + .HasColumnName("average_item_level"); + + b.Property("CharacterId") + .HasColumnType("bigint") + .HasColumnName("character_id"); + + b.Property("ChromieTime") + .HasColumnType("integer") + .HasColumnName("chromie_time"); + + b.Property("ClassId") + .HasColumnType("integer") + .HasColumnName("class_id"); + + b.Property("Copper") + .HasColumnType("bigint") + .HasColumnName("copper"); + + b.Property("EquippedItemLevel") + .HasColumnType("integer") + .HasColumnName("equipped_item_level"); + + b.Property("Experience") + .HasColumnType("integer") + .HasColumnName("experience"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.Property("Gender") + .HasColumnType("integer") + .HasColumnName("gender"); + + b.Property("GuildId") + .HasColumnType("integer") + .HasColumnName("guild_id"); + + b.Property("IsResting") + .HasColumnType("boolean") + .HasColumnName("is_resting"); + + b.Property("IsWarMode") + .HasColumnType("boolean") + .HasColumnName("is_war_mode"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("LastApiModified") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_modified"); + + b.Property("LastSeenAddon") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_addon"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("PlayedTotal") + .HasColumnType("integer") + .HasColumnName("played_total"); + + b.Property("RaceId") + .HasColumnType("integer") + .HasColumnName("race_id"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property("RestedExperience") + .HasColumnType("integer") + .HasColumnName("rested_experience"); + + b.Property("ShouldUpdate") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("should_update"); + + b.HasKey("Id") + .HasName("pk_player_character"); + + b.HasIndex("AccountId") + .HasDatabaseName("ix_player_character_account_id"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_player_character_guild_id"); + + b.HasIndex("LastApiCheck") + .HasDatabaseName("ix_player_character_last_api_check") + .HasFilter("should_update = true AND account_id IS NOT NULL"); + + NpgsqlIndexBuilderExtensions.IncludeProperties(b.HasIndex("LastApiCheck"), new[] { "Id", "AccountId", "Name", "LastApiModified" }); + + b.HasIndex("CharacterId", "LastSeenAddon") + .HasDatabaseName("ix_player_character_character_id_last_seen_addon") + .HasFilter("account_id IS NOT NULL"); + + b.HasIndex("RealmId", "Name") + .IsUnique() + .HasDatabaseName("ix_player_character_realm_id_name"); + + b.ToTable("player_character", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAchievements", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CompressedCriteriaIds") + .HasColumnType("bytea") + .HasColumnName("compressed_criteria_ids"); + + b.PrimitiveCollection>("CriteriaAmounts") + .HasColumnType("bigint[]") + .HasColumnName("criteria_amounts"); + + b.PrimitiveCollection>("CriteriaCompleted") + .HasColumnType("boolean[]") + .HasColumnName("criteria_completed"); + + b.PrimitiveCollection>("CriteriaIds") + .HasColumnType("integer[]") + .HasColumnName("criteria_ids"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_achievements"); + + b.ToTable("player_character_achievements", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonAchievements", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Achievements") + .HasColumnType("jsonb") + .HasColumnName("achievements"); + + b.Property("ScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_achievements"); + + b.ToTable("player_character_addon_achievements", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonData", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Auras") + .HasColumnType("jsonb") + .HasColumnName("auras"); + + b.Property("BagsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("bags_scanned_at"); + + b.Property("BankScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("bank_scanned_at"); + + b.Property("BankTabs") + .HasColumnType("smallint") + .HasColumnName("bank_tabs"); + + b.Property("BindLocation") + .HasColumnType("text") + .HasColumnName("bind_location"); + + b.Property>("Currencies") + .HasColumnType("jsonb") + .HasColumnName("currencies"); + + b.Property("CurrenciesScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("currencies_scanned_at"); + + b.Property("CurrenciesTransferredAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("currencies_transferred_at"); + + b.Property("CurrentLocation") + .HasColumnType("text") + .HasColumnName("current_location"); + + b.Property("DailyReset") + .HasColumnType("timestamp with time zone") + .HasColumnName("daily_reset"); + + b.Property>("EquippedItems") + .HasColumnType("jsonb") + .HasColumnName("equipped_items"); + + b.Property>>>("GarrisonTrees") + .HasColumnType("jsonb") + .HasColumnName("garrison_trees"); + + b.Property("GarrisonTreesScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("garrison_trees_scanned_at"); + + b.Property>("Garrisons") + .HasColumnType("jsonb") + .HasColumnName("garrisons"); + + b.Property>("HighestItemLevel") + .HasColumnType("jsonb") + .HasColumnName("highest_item_level"); + + b.PrimitiveCollection>("KnownSpells") + .HasColumnType("integer[]") + .HasColumnName("known_spells"); + + b.Property("Level") + .HasColumnType("smallint") + .HasColumnName("level"); + + b.Property("LevelXp") + .HasColumnType("integer") + .HasColumnName("level_xp"); + + b.Property>("MythicPlus") + .HasColumnType("jsonb") + .HasColumnName("mythic_plus"); + + b.Property("MythicPlusScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("mythic_plus_scanned_at"); + + b.Property>>("MythicPlusSeasons") + .HasColumnType("jsonb") + .HasColumnName("mythic_plus_seasons"); + + b.Property>>("MythicPlusWeeks") + .HasColumnType("jsonb") + .HasColumnName("mythic_plus_weeks"); + + b.Property>("Paragons") + .HasColumnType("jsonb") + .HasColumnName("paragons"); + + b.Property>>("PatronOrders") + .HasColumnType("jsonb") + .HasColumnName("patron_orders"); + + b.Property("PatronOrdersScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("patron_orders_scanned_at"); + + b.Property>>("ProfessionCooldowns") + .HasColumnType("jsonb") + .HasColumnName("profession_cooldowns"); + + b.Property>>("ProfessionTraits") + .HasColumnType("jsonb") + .HasColumnName("profession_traits"); + + b.Property>("Professions") + .HasColumnType("jsonb") + .HasColumnName("professions"); + + b.Property>("Reputations") + .HasColumnType("jsonb") + .HasColumnName("reputations"); + + b.Property("ReputationsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reputations_scanned_at"); + + b.Property("WeeklyReset") + .HasColumnType("timestamp with time zone") + .HasColumnName("weekly_reset"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_data"); + + b.ToTable("player_character_addon_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonMounts", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("Mounts") + .HasColumnType("integer[]") + .HasColumnName("mounts"); + + b.Property("ScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_mounts"); + + b.ToTable("player_character_addon_mounts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonQuests", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CallingsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("callings_scanned_at"); + + b.PrimitiveCollection>("CompletedQuests") + .HasColumnType("integer[]") + .HasColumnName("completed_quests"); + + b.Property("CompletedQuestsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("completed_quests_scanned_at"); + + b.Property("CompressedCompletedIds") + .HasColumnType("bytea") + .HasColumnName("compressed_completed_ids"); + + b.Property>>>("Dailies") + .HasColumnType("jsonb") + .HasColumnName("dailies"); + + b.Property>>("GoldWorldQuests") + .HasColumnType("jsonb") + .HasColumnName("gold_world_quests"); + + b.Property>("ProgressQuests") + .HasColumnType("jsonb") + .HasColumnName("progress_quests"); + + b.Property("QuestsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("quests_scanned_at"); + + b.Property("WorldQuestsScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("world_quests_scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_addon_quests"); + + b.ToTable("player_character_addon_quests", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterConfiguration", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("BackgroundBrightness") + .HasColumnType("smallint") + .HasColumnName("background_brightness"); + + b.Property("BackgroundId") + .HasColumnType("smallint") + .HasColumnName("background_id"); + + b.Property("BackgroundSaturation") + .HasColumnType("smallint") + .HasColumnName("background_saturation"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_configuration"); + + b.ToTable("player_character_configuration", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterEquippedItems", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Items") + .HasColumnType("jsonb") + .HasColumnName("items"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_equipped_items"); + + b.ToTable("player_character_equipped_items", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("smallint[]") + .HasColumnName("bonus_ids"); + + b.Property("Bound") + .HasColumnType("boolean") + .HasColumnName("bound"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("ContainerId") + .HasColumnType("smallint") + .HasColumnName("container_id"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CraftedQuality") + .HasColumnType("smallint") + .HasColumnName("crafted_quality"); + + b.Property("EnchantId") + .HasColumnType("smallint") + .HasColumnName("enchant_id"); + + b.PrimitiveCollection>("Gems") + .HasColumnType("integer[]") + .HasColumnName("gems"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property("Location") + .HasColumnType("smallint") + .HasColumnName("location"); + + b.Property>("Modifiers") + .HasColumnType("jsonb") + .HasColumnName("modifiers"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("Slot") + .HasColumnType("smallint") + .HasColumnName("slot"); + + b.Property("SuffixId") + .HasColumnType("smallint") + .HasColumnName("suffix_id"); + + b.HasKey("Id") + .HasName("pk_player_character_item"); + + b.HasIndex("CharacterId", "Slot") + .HasDatabaseName("ix_player_character_item_character_id_slot"); + + b.HasIndex("CharacterId", "ItemId", "Location") + .HasDatabaseName("ix_player_character_item_character_id_item_id_location"); + + b.ToTable("player_character_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterLockouts", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("LastUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_updated"); + + b.Property>("Lockouts") + .HasColumnType("jsonb") + .HasColumnName("lockouts"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_lockouts"); + + b.ToTable("player_character_lockouts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMedia", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("AvatarUrl") + .HasColumnType("text") + .HasColumnName("avatar_url"); + + b.Property("InsetUrl") + .HasColumnType("text") + .HasColumnName("inset_url"); + + b.Property("MainRawUrl") + .HasColumnType("text") + .HasColumnName("main_raw_url"); + + b.Property("MainUrl") + .HasColumnType("text") + .HasColumnName("main_url"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_media"); + + b.ToTable("player_character_media", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMounts", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("Mounts") + .HasColumnType("integer[]") + .HasColumnName("mounts"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_mounts"); + + b.ToTable("player_character_mounts", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlus", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CurrentPeriodId") + .HasColumnType("integer") + .HasColumnName("current_period_id"); + + b.Property>("PeriodRuns") + .HasColumnType("jsonb") + .HasColumnName("period_runs"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_mythic_plus"); + + b.ToTable("player_character_mythic_plus", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusAddon", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Maps") + .HasColumnType("jsonb") + .HasColumnName("maps"); + + b.Property("Season") + .HasColumnType("integer") + .HasColumnName("season"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_mythic_plus_addon"); + + b.ToTable("player_character_mythic_plus_addon", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusSeason", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Season") + .HasColumnType("integer") + .HasColumnName("season"); + + b.Property("Rating") + .HasColumnType("double precision") + .HasColumnName("rating"); + + b.Property>("Runs") + .HasColumnType("jsonb") + .HasColumnName("runs"); + + b.HasKey("CharacterId", "Season") + .HasName("pk_player_character_mythic_plus_season"); + + b.ToTable("player_character_mythic_plus_season", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterProfessions", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("ProfessionSpecializations") + .HasColumnType("jsonb") + .HasColumnName("profession_specializations"); + + b.Property>>("Professions") + .HasColumnType("jsonb") + .HasColumnName("professions"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_professions"); + + b.ToTable("player_character_professions", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterQuests", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("CompletedIds") + .HasColumnType("integer[]") + .HasColumnName("completed_ids"); + + b.Property("CompressedCompletedIds") + .HasColumnType("bytea") + .HasColumnName("compressed_completed_ids"); + + b.Property("ScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("scanned_at"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_quests"); + + b.ToTable("player_character_quests", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterRaiderIo", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Seasons") + .HasColumnType("jsonb") + .HasColumnName("seasons"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_raider_io"); + + b.ToTable("player_character_raider_io", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterReputations", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("ExtraReputationIds") + .HasColumnType("integer[]") + .HasColumnName("extra_reputation_ids"); + + b.PrimitiveCollection>("ExtraReputationValues") + .HasColumnType("integer[]") + .HasColumnName("extra_reputation_values"); + + b.Property>("Paragons") + .HasColumnType("jsonb") + .HasColumnName("paragons"); + + b.PrimitiveCollection>("ReputationIds") + .HasColumnType("integer[]") + .HasColumnName("reputation_ids"); + + b.PrimitiveCollection>("ReputationValues") + .HasColumnType("integer[]") + .HasColumnName("reputation_values"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_reputations"); + + b.ToTable("player_character_reputations", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterShadowlands", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("ConduitIds") + .HasColumnType("integer[]") + .HasColumnName("conduit_ids"); + + b.PrimitiveCollection>("ConduitRanks") + .HasColumnType("integer[]") + .HasColumnName("conduit_ranks"); + + b.Property("CovenantId") + .HasColumnType("integer") + .HasColumnName("covenant_id"); + + b.Property>("Covenants") + .HasColumnType("jsonb") + .HasColumnName("covenants"); + + b.Property("RenownLevel") + .HasColumnType("integer") + .HasColumnName("renown_level"); + + b.Property("SoulbindId") + .HasColumnType("integer") + .HasColumnName("soulbind_id"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_shadowlands"); + + b.ToTable("player_character_shadowlands", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterSpecializations", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Specializations") + .HasColumnType("jsonb") + .HasColumnName("specializations"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_specializations"); + + b.ToTable("player_character_specializations", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStatistics", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("StatisticDescriptions") + .HasColumnType("text[]") + .HasColumnName("statistic_descriptions"); + + b.PrimitiveCollection>("StatisticIds") + .HasColumnType("integer[]") + .HasColumnName("statistic_ids"); + + b.PrimitiveCollection>("StatisticQuantities") + .HasColumnType("integer[]") + .HasColumnName("statistic_quantities"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_statistics"); + + b.ToTable("player_character_statistics", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStats", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property>("Basic") + .HasColumnType("jsonb") + .HasColumnName("basic"); + + b.Property>("Misc") + .HasColumnType("jsonb") + .HasColumnName("misc"); + + b.Property>("Rating") + .HasColumnType("jsonb") + .HasColumnName("rating"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_stats"); + + b.ToTable("player_character_stats", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterTransmog", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.PrimitiveCollection>("IllusionIds") + .HasColumnType("integer[]") + .HasColumnName("illusion_ids"); + + b.PrimitiveCollection>("TransmogIds") + .HasColumnType("integer[]") + .HasColumnName("transmog_ids"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_transmog"); + + b.ToTable("player_character_transmog", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterWeekly", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("DelveGilded") + .HasColumnType("smallint") + .HasColumnName("delve_gilded"); + + b.PrimitiveCollection>("DelveLevels") + .HasColumnType("integer[]") + .HasColumnName("delve_levels"); + + b.PrimitiveCollection>("DelveMaps") + .HasColumnType("text[]") + .HasColumnName("delve_maps"); + + b.Property("DelveWeek") + .HasColumnType("integer") + .HasColumnName("delve_week"); + + b.Property("KeystoneDungeon") + .HasColumnType("integer") + .HasColumnName("keystone_dungeon"); + + b.Property("KeystoneLevel") + .HasColumnType("integer") + .HasColumnName("keystone_level"); + + b.Property("KeystoneScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("keystone_scanned_at"); + + b.Property>("Torghast") + .HasColumnType("jsonb") + .HasColumnName("torghast"); + + b.Property("TorghastScannedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("torghast_scanned_at"); + + b.Property("Vault") + .HasColumnType("jsonb") + .HasColumnName("vault"); + + b.HasKey("CharacterId") + .HasName("pk_player_character_weekly"); + + b.ToTable("player_character_weekly", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuild", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property>("Tabs") + .HasColumnType("jsonb") + .HasColumnName("tabs"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_player_guild"); + + b.HasIndex("UserId", "RealmId", "Name") + .IsUnique() + .HasDatabaseName("ix_player_guild_user_id_realm_id_name"); + + b.ToTable("player_guild", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuildItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("smallint[]") + .HasColumnName("bonus_ids"); + + b.Property("Bound") + .HasColumnType("boolean") + .HasColumnName("bound"); + + b.Property("ContainerId") + .HasColumnType("smallint") + .HasColumnName("container_id"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CraftedQuality") + .HasColumnType("smallint") + .HasColumnName("crafted_quality"); + + b.Property("EnchantId") + .HasColumnType("smallint") + .HasColumnName("enchant_id"); + + b.PrimitiveCollection>("Gems") + .HasColumnType("integer[]") + .HasColumnName("gems"); + + b.Property("GuildId") + .HasColumnType("integer") + .HasColumnName("guild_id"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property>("Modifiers") + .HasColumnType("jsonb") + .HasColumnName("modifiers"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("Slot") + .HasColumnType("smallint") + .HasColumnName("slot"); + + b.Property("SuffixId") + .HasColumnType("smallint") + .HasColumnName("suffix_id"); + + b.HasKey("Id") + .HasName("pk_player_guild_item"); + + b.HasIndex("GuildId", "ItemId") + .HasDatabaseName("ix_player_guild_item_guild_id_item_id"); + + b.ToTable("player_guild_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerWarbankItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("smallint[]") + .HasColumnName("bonus_ids"); + + b.Property("Bound") + .HasColumnType("boolean") + .HasColumnName("bound"); + + b.Property("ContainerId") + .HasColumnType("smallint") + .HasColumnName("container_id"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CraftedQuality") + .HasColumnType("smallint") + .HasColumnName("crafted_quality"); + + b.Property("EnchantId") + .HasColumnType("smallint") + .HasColumnName("enchant_id"); + + b.PrimitiveCollection>("Gems") + .HasColumnType("integer[]") + .HasColumnName("gems"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property>("Modifiers") + .HasColumnType("jsonb") + .HasColumnName("modifiers"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Slot") + .HasColumnType("smallint") + .HasColumnName("slot"); + + b.Property("SuffixId") + .HasColumnType("smallint") + .HasColumnName("suffix_id"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_player_warbank_item"); + + b.HasIndex("UserId", "ItemId") + .HasDatabaseName("ix_player_warbank_item_user_id_item_id"); + + b.ToTable("player_warbank_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.AccountTransmogQuery", b => + { + b.PrimitiveCollection>("IllusionIds") + .HasColumnType("integer[]") + .HasColumnName("illusion_ids"); + + b.PrimitiveCollection>("TransmogIds") + .HasColumnType("integer[]") + .HasColumnName("transmog_ids"); + + b.ToTable("AccountTransmogQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.AchievementCriteriaQuery", b => + { + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CriteriaId") + .HasColumnType("integer") + .HasColumnName("criteria_id"); + + b.ToTable("AchievementCriteriaQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.ActiveConnectedRealmQuery", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.ToTable("ActiveConnectedRealmQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.AuctionBrowseQuery", b => + { + b.Property("GroupKey") + .HasColumnType("text") + .HasColumnName("group_key"); + + b.Property("LowestBuyoutPrice") + .HasColumnType("bigint") + .HasColumnName("lowest_buyout_price"); + + b.Property("TotalQuantity") + .HasColumnType("bigint") + .HasColumnName("total_quantity"); + + b.ToTable("AuctionBrowseQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.CompletedAchievementsQuery", b => + { + b.Property("AchievementId") + .HasColumnType("integer") + .HasColumnName("achievement_id"); + + b.Property("Timestamp") + .HasColumnType("integer") + .HasColumnName("timestamp"); + + b.ToTable("CompletedAchievementsQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.LatestPlayerAccountGoldSnapshotQuery", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.ToTable("LatestPlayerAccountGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.LatestUserGoldSnapshotQuery", b => + { + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("LatestUserGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.MountQuery", b => + { + b.PrimitiveCollection>("AddonMounts") + .HasColumnType("integer[]") + .HasColumnName("addon_mounts"); + + b.PrimitiveCollection>("Mounts") + .HasColumnType("integer[]") + .HasColumnName("mounts"); + + b.ToTable("MountQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.PlayerAccountGoldSnapshotQuery", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("RealmId") + .HasColumnType("integer") + .HasColumnName("realm_id"); + + b.Property("TotalGold") + .HasColumnType("integer") + .HasColumnName("total_gold"); + + b.ToTable("PlayerAccountGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.SchedulerCharacterQuery", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CharacterName") + .HasColumnType("text") + .HasColumnName("character_name"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("LastApiModified") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_modified"); + + b.Property("RealmSlug") + .HasColumnType("text") + .HasColumnName("realm_slug"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("SchedulerCharacterQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.SchedulerUserQuery", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("SchedulerUserQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.StatisticsQuery", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Quantity") + .HasColumnType("integer") + .HasColumnName("quantity"); + + b.Property("StatisticId") + .HasColumnType("integer") + .HasColumnName("statistic_id"); + + b.ToTable("StatisticsQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.UserGoldSnapshotQuery", b => + { + b.Property("TotalGold") + .HasColumnType("integer") + .HasColumnName("total_gold"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("UserGoldSnapshotQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Query.UserLeaderboardQuery", b => + { + b.Property("AppearanceIdCount") + .HasColumnType("integer") + .HasColumnName("appearance_id_count"); + + b.Property("AppearanceSourceCount") + .HasColumnType("integer") + .HasColumnName("appearance_source_count"); + + b.Property("CompletedQuestCount") + .HasColumnType("integer") + .HasColumnName("completed_quest_count"); + + b.Property("IllusionCount") + .HasColumnType("smallint") + .HasColumnName("illusion_count"); + + b.Property("MountCount") + .HasColumnType("smallint") + .HasColumnName("mount_count"); + + b.Property("ToyCount") + .HasColumnType("smallint") + .HasColumnName("toy_count"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.ToTable("UserLeaderboardQuery", null, t => + { + t.ExcludeFromMigrations(); + }); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.QueuedJob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .HasColumnType("text") + .HasColumnName("data"); + + b.Property("DataHash") + .HasColumnType("text") + .HasColumnName("data_hash"); + + b.Property("Failures") + .HasColumnType("smallint") + .HasColumnName("failures"); + + b.Property("Priority") + .HasColumnType("smallint") + .HasColumnName("priority"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("started_at"); + + b.Property("Type") + .HasColumnType("smallint") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_queued_job"); + + b.HasIndex("Priority") + .HasDatabaseName("ix_queued_job_priority") + .HasFilter("started_at IS NULL"); + + b.HasIndex("Priority", "Type", "DataHash") + .IsUnique() + .HasDatabaseName("ix_queued_job_priority_type_data_hash"); + + b.ToTable("queued_job", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.Team", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DefaultRealmId") + .HasColumnType("integer") + .HasColumnName("default_realm_id"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Guid") + .HasColumnType("uuid") + .HasColumnName("guid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_team"); + + b.HasIndex("Guid") + .IsUnique() + .HasDatabaseName("ix_team_guid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_team_user_id"); + + b.ToTable("team", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.TeamCharacter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("PrimaryRole") + .HasColumnType("smallint") + .HasColumnName("primary_role"); + + b.Property("SecondaryRole") + .HasColumnType("smallint") + .HasColumnName("secondary_role"); + + b.Property("TeamId") + .HasColumnType("integer") + .HasColumnName("team_id"); + + b.HasKey("Id") + .HasName("pk_team_character"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_team_character_character_id"); + + b.HasIndex("TeamId") + .HasDatabaseName("ix_team_character_team_id"); + + b.ToTable("team_character", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserAddonData", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("WarbankCopper") + .HasColumnType("bigint") + .HasColumnName("warbank_copper"); + + b.Property("WarbankGoldUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("warbank_gold_updated_at"); + + b.Property("WarbankUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("warbank_updated_at"); + + b.HasKey("UserId") + .HasName("pk_user_addon_data"); + + b.ToTable("user_addon_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserBulkData", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property>("Heirlooms") + .HasColumnType("jsonb") + .HasColumnName("heirlooms"); + + b.Property("HeirloomsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("heirlooms_updated_at"); + + b.PrimitiveCollection>("MountIds") + .HasColumnType("smallint[]") + .HasColumnName("mount_ids"); + + b.Property("MountsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("mounts_updated_at"); + + b.Property>("Pets") + .HasColumnType("jsonb") + .HasColumnName("pets"); + + b.Property("PetsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("pets_updated_at"); + + b.PrimitiveCollection>("ToyIds") + .HasColumnType("smallint[]") + .HasColumnName("toy_ids"); + + b.Property("ToysUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("toys_updated_at"); + + b.PrimitiveCollection>("TransmogIds") + .HasColumnType("integer[]") + .HasColumnName("transmog_ids"); + + b.Property("TransmogsUpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("transmogs_updated_at"); + + b.HasKey("UserId") + .HasName("pk_user_bulk_data"); + + b.ToTable("user_bulk_data", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserCache", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.PrimitiveCollection>("AppearanceIds") + .HasColumnType("integer[]") + .HasColumnName("appearance_ids"); + + b.PrimitiveCollection>("AppearanceSources") + .HasColumnType("text[]") + .HasColumnName("appearance_sources"); + + b.Property("CompletedQuests") + .HasColumnType("integer") + .HasColumnName("completed_quests"); + + b.PrimitiveCollection>("IllusionIds") + .HasColumnType("smallint[]") + .HasColumnName("illusion_ids"); + + b.PrimitiveCollection>("MountIds") + .HasColumnType("smallint[]") + .HasColumnName("mount_ids"); + + b.Property("MountsUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("mounts_updated"); + + b.PrimitiveCollection>("ToyIds") + .HasColumnType("smallint[]") + .HasColumnName("toy_ids"); + + b.Property("ToysUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("toys_updated"); + + b.Property("TransmogUpdated") + .HasColumnType("timestamp with time zone") + .HasColumnName("transmog_updated"); + + b.HasKey("UserId") + .HasName("pk_user_cache"); + + b.ToTable("user_cache", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserGoldSnapshot", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_gold_snapshot"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_gold_snapshot_user_id"); + + b.ToTable("user_gold_snapshot", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserLeaderboardSnapshot", b => + { + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("Date") + .HasColumnType("date") + .HasColumnName("date"); + + b.Property("AchievementPointsAlliance") + .HasColumnType("integer") + .HasColumnName("achievement_points_alliance"); + + b.Property("AchievementPointsHorde") + .HasColumnType("integer") + .HasColumnName("achievement_points_horde"); + + b.Property("AchievementPointsOverall") + .HasColumnType("integer") + .HasColumnName("achievement_points_overall"); + + b.Property("AppearanceIdCount") + .HasColumnType("integer") + .HasColumnName("appearance_id_count"); + + b.Property("AppearanceSourceCount") + .HasColumnType("integer") + .HasColumnName("appearance_source_count"); + + b.Property("CompletedQuestCount") + .HasColumnType("integer") + .HasColumnName("completed_quest_count"); + + b.Property("HeirloomCount") + .HasColumnType("smallint") + .HasColumnName("heirloom_count"); + + b.Property("HeirloomLevels") + .HasColumnType("smallint") + .HasColumnName("heirloom_levels"); + + b.Property("IllusionCount") + .HasColumnType("smallint") + .HasColumnName("illusion_count"); + + b.Property("MountCount") + .HasColumnType("smallint") + .HasColumnName("mount_count"); + + b.Property("PetCount") + .HasColumnType("smallint") + .HasColumnName("pet_count"); + + b.Property("RecipeCount") + .HasColumnType("smallint") + .HasColumnName("recipe_count"); + + b.Property("ReputationCount") + .HasColumnType("smallint") + .HasColumnName("reputation_count"); + + b.Property("TitleCount") + .HasColumnType("smallint") + .HasColumnName("title_count"); + + b.Property("ToyCount") + .HasColumnType("smallint") + .HasColumnName("toy_count"); + + b.HasKey("UserId", "Date") + .HasName("pk_user_leaderboard_snapshot"); + + b.HasIndex("UserId", "Date") + .IsDescending(false, true) + .HasDatabaseName("ix_user_leaderboard_snapshot_user_id_date"); + + b.ToTable("user_leaderboard_snapshot", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.WorldQuestAggregate", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ZoneId") + .HasColumnType("integer") + .HasColumnName("zone_id"); + + b.Property("QuestId") + .HasColumnType("integer") + .HasColumnName("quest_id"); + + b.Property("JsonData") + .HasColumnType("text") + .HasColumnName("json_data"); + + b.HasKey("Region", "ZoneId", "QuestId") + .HasName("pk_world_quest_aggregate"); + + b.ToTable("world_quest_aggregate", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.WorldQuestReport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Class") + .HasColumnType("smallint") + .HasColumnName("class"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.Property("Location") + .HasColumnType("text") + .HasColumnName("location"); + + b.Property("QuestId") + .HasColumnType("integer") + .HasColumnName("quest_id"); + + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ReportedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("reported_at"); + + b.Property>("Rewards") + .HasColumnType("jsonb") + .HasColumnName("rewards"); + + b.Property("UserId") + .HasColumnType("bigint") + .HasColumnName("user_id"); + + b.Property("ZoneId") + .HasColumnType("integer") + .HasColumnName("zone_id"); + + b.HasKey("Id") + .HasName("pk_world_quest_report"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_world_quest_report_user_id"); + + b.HasIndex("Region", "ExpiresAt") + .IsDescending(false, true) + .HasDatabaseName("ix_world_quest_report_region_expires_at"); + + b.ToTable("world_quest_report", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuction", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("AuctionId") + .HasColumnType("integer") + .HasColumnName("auction_id"); + + b.Property("AppearanceId") + .HasColumnType("integer") + .HasColumnName("appearance_id"); + + b.Property("AppearanceSource") + .HasColumnType("text") + .HasColumnName("appearance_source"); + + b.Property("BidPrice") + .HasColumnType("bigint") + .HasColumnName("bid_price"); + + b.PrimitiveCollection>("BonusIds") + .HasColumnType("integer[]") + .HasColumnName("bonus_ids"); + + b.Property("BuyoutPrice") + .HasColumnType("bigint") + .HasColumnName("buyout_price"); + + b.Property("Context") + .HasColumnType("smallint") + .HasColumnName("context"); + + b.Property("GroupKey") + .HasColumnType("text") + .HasColumnName("group_key"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.PrimitiveCollection>("ModifierTypes") + .HasColumnType("smallint[]") + .HasColumnName("modifier_types"); + + b.PrimitiveCollection>("ModifierValues") + .HasColumnType("integer[]") + .HasColumnName("modifier_values"); + + b.Property("PetBreedId") + .HasColumnType("smallint") + .HasColumnName("pet_breed_id"); + + b.Property("PetLevel") + .HasColumnType("smallint") + .HasColumnName("pet_level"); + + b.Property("PetQuality") + .HasColumnType("smallint") + .HasColumnName("pet_quality"); + + b.Property("PetSpeciesId") + .HasColumnType("smallint") + .HasColumnName("pet_species_id"); + + b.Property("Quantity") + .HasColumnType("integer") + .HasColumnName("quantity"); + + b.Property("TimeLeft") + .HasColumnType("smallint") + .HasColumnName("time_left"); + + b.HasKey("ConnectedRealmId", "AuctionId") + .HasName("pk_wow_auction"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_wow_auction_item_id"); + + b.HasIndex("PetSpeciesId") + .HasDatabaseName("ix_wow_auction_pet_species_id"); + + b.HasIndex("AppearanceId", "BuyoutPrice") + .HasDatabaseName("ix_wow_auction_appearance_id_buyout_price") + .HasFilter("appearance_id IS NOT NULL"); + + b.HasIndex("AppearanceSource", "BuyoutPrice") + .HasDatabaseName("ix_wow_auction_appearance_source_buyout_price") + .HasFilter("appearance_source IS NOT NULL"); + + b.ToTable("wow_auction", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCheapestByAppearanceId", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("AppearanceId") + .HasColumnType("integer") + .HasColumnName("appearance_id"); + + b.Property("AuctionId") + .HasColumnType("integer") + .HasColumnName("auction_id"); + + b.HasKey("ConnectedRealmId", "AppearanceId") + .HasName("pk_wow_auction_cheapest_by_appearance_id"); + + b.ToTable("wow_auction_cheapest_by_appearance_id", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCheapestByAppearanceSource", b => + { + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("AppearanceSource") + .HasColumnType("text") + .HasColumnName("appearance_source"); + + b.Property("AuctionId") + .HasColumnType("integer") + .HasColumnName("auction_id"); + + b.HasKey("ConnectedRealmId", "AppearanceSource") + .HasName("pk_wow_auction_cheapest_by_appearance_source"); + + b.ToTable("wow_auction_cheapest_by_appearance_source", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCommodityDaily", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Date") + .HasColumnType("date") + .HasColumnName("date"); + + b.PrimitiveCollection>("AvgData") + .HasColumnType("integer[]") + .HasColumnName("avg_data"); + + b.Property("ListedMax") + .HasColumnType("integer") + .HasColumnName("listed_max"); + + b.Property("ListedMin") + .HasColumnType("integer") + .HasColumnName("listed_min"); + + b.PrimitiveCollection>("MaxData") + .HasColumnType("integer[]") + .HasColumnName("max_data"); + + b.PrimitiveCollection>("MinData") + .HasColumnType("integer[]") + .HasColumnName("min_data"); + + b.HasKey("Region", "ItemId", "Date") + .HasName("pk_wow_auction_commodity_daily"); + + b.ToTable("wow_auction_commodity_daily", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowAuctionCommodityHourly", b => + { + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.PrimitiveCollection>("Data") + .HasColumnType("integer[]") + .HasColumnName("data"); + + b.Property("Listed") + .HasColumnType("integer") + .HasColumnName("listed"); + + b.HasKey("Region", "ItemId", "Timestamp") + .HasName("pk_wow_auction_commodity_hourly"); + + b.ToTable("wow_auction_commodity_hourly", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCampaign", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.PrimitiveCollection>("QuestLineIds") + .HasColumnType("integer[]") + .HasColumnName("quest_line_ids"); + + b.HasKey("Id") + .HasName("pk_wow_campaign"); + + b.ToTable("wow_campaign", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowChallengeDungeon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("MapId") + .HasColumnType("smallint") + .HasColumnName("map_id"); + + b.PrimitiveCollection>("TimerBreakpoints") + .HasColumnType("smallint[]") + .HasColumnName("timer_breakpoints"); + + b.HasKey("Id") + .HasName("pk_wow_challenge_dungeon"); + + b.ToTable("wow_challenge_dungeon", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCharacterClass", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArmorMask") + .HasColumnType("smallint") + .HasColumnName("armor_mask"); + + b.Property("RolesMask") + .HasColumnType("smallint") + .HasColumnName("roles_mask"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.HasKey("Id") + .HasName("pk_wow_character_class"); + + b.ToTable("wow_character_class", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCharacterRace", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Bit") + .HasColumnType("smallint") + .HasColumnName("bit"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.HasKey("Id") + .HasName("pk_wow_character_race"); + + b.ToTable("wow_character_race", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCharacterSpecialization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.Property("Order") + .HasColumnType("smallint") + .HasColumnName("order"); + + b.Property("PrimaryStat") + .HasColumnType("smallint") + .HasColumnName("primary_stat"); + + b.Property("Role") + .HasColumnType("smallint") + .HasColumnName("role"); + + b.HasKey("Id") + .HasName("pk_wow_character_specialization"); + + b.ToTable("wow_character_specialization", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("smallint") + .HasColumnName("category_id"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("MaxPerWeek") + .HasColumnType("integer") + .HasColumnName("max_per_week"); + + b.Property("MaxTotal") + .HasColumnType("integer") + .HasColumnName("max_total"); + + b.Property("RechargeAmount") + .HasColumnType("smallint") + .HasColumnName("recharge_amount"); + + b.Property("RechargeInterval") + .HasColumnType("bigint") + .HasColumnName("recharge_interval"); + + b.Property("TransferPercent") + .HasColumnType("smallint") + .HasColumnName("transfer_percent"); + + b.HasKey("Id") + .HasName("pk_wow_currency"); + + b.ToTable("wow_currency", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowCurrencyCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.HasKey("Id") + .HasName("pk_wow_currency_category"); + + b.ToTable("wow_currency_category", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowDecor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Type") + .HasColumnType("smallint") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_wow_decor"); + + b.ToTable("wow_decor", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowHoliday", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DescriptionId") + .HasColumnType("smallint") + .HasColumnName("description_id"); + + b.PrimitiveCollection>("Durations") + .HasColumnType("smallint[]") + .HasColumnName("durations"); + + b.Property("FilterType") + .HasColumnType("smallint") + .HasColumnName("filter_type"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("Looping") + .HasColumnType("smallint") + .HasColumnName("looping"); + + b.Property("NameId") + .HasColumnType("smallint") + .HasColumnName("name_id"); + + b.Property("Priority") + .HasColumnType("smallint") + .HasColumnName("priority"); + + b.Property("Region") + .HasColumnType("smallint") + .HasColumnName("region"); + + b.PrimitiveCollection>("StartDates") + .HasColumnType("timestamp with time zone[]") + .HasColumnName("start_dates"); + + b.HasKey("Id") + .HasName("pk_wow_holiday"); + + b.ToTable("wow_holiday", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BindType") + .HasColumnType("smallint") + .HasColumnName("bind_type"); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.Property("ClassMask") + .HasColumnType("integer") + .HasColumnName("class_mask"); + + b.PrimitiveCollection("CompletesQuestIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("completes_quest_ids"); + + b.Property("ContainerSlots") + .HasColumnType("smallint") + .HasColumnName("container_slots"); + + b.Property("CraftingQuality") + .HasColumnType("smallint") + .HasColumnName("crafting_quality"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("InventoryType") + .HasColumnType("smallint") + .HasColumnName("inventory_type"); + + b.Property("ItemLevel") + .HasColumnType("smallint") + .HasColumnName("item_level"); + + b.Property("LimitCategory") + .HasColumnType("smallint") + .HasColumnName("limit_category"); + + b.Property("OppositeFactionId") + .HasColumnType("integer") + .HasColumnName("opposite_faction_id"); + + b.Property("PrimaryStat") + .HasColumnType("smallint") + .HasColumnName("primary_stat"); + + b.Property("Quality") + .HasColumnType("smallint") + .HasColumnName("quality"); + + b.Property("RaceMask") + .HasColumnType("bigint") + .HasColumnName("race_mask"); + + b.Property("RequiredAbility") + .HasColumnType("integer") + .HasColumnName("required_ability"); + + b.Property("RequiredLevel") + .HasColumnType("smallint") + .HasColumnName("required_level"); + + b.Property("RequiredSkill") + .HasColumnType("smallint") + .HasColumnName("required_skill"); + + b.Property("RequiredSkillRank") + .HasColumnType("smallint") + .HasColumnName("required_skill_rank"); + + b.PrimitiveCollection("Sockets") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("smallint[]") + .HasDefaultValue(new short[0]) + .HasColumnName("sockets"); + + b.Property("Stackable") + .HasColumnType("integer") + .HasColumnName("stackable"); + + b.Property("SubclassId") + .HasColumnType("smallint") + .HasColumnName("subclass_id"); + + b.PrimitiveCollection("TeachesDecorIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_decor_ids"); + + b.PrimitiveCollection("TeachesSpellIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_spell_ids"); + + b.PrimitiveCollection("TeachesTransmogIllusionIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_transmog_illusion_ids"); + + b.PrimitiveCollection("TeachesTransmogSetIds") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("integer[]") + .HasDefaultValue(new int[0]) + .HasColumnName("teaches_transmog_set_ids"); + + b.Property("Unique") + .HasColumnType("smallint") + .HasColumnName("unique"); + + b.HasKey("Id") + .HasName("pk_wow_item"); + + b.ToTable("wow_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemBonus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BonusTypeFlags") + .HasColumnType("bigint") + .HasColumnName("bonus_type_flags"); + + b.Property>>("Bonuses") + .HasColumnType("jsonb") + .HasColumnName("bonuses"); + + b.HasKey("Id") + .HasName("pk_wow_item_bonus"); + + b.ToTable("wow_item_bonus", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemClass", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.HasKey("Id") + .HasName("pk_wow_item_class"); + + b.ToTable("wow_item_class", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemEffect", b => + { + b.Property("ItemXItemEffectId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("item_x_item_effect_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemXItemEffectId")); + + b.Property("Effect") + .HasColumnType("integer") + .HasColumnName("effect"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.PrimitiveCollection("Values") + .HasColumnType("integer[]") + .HasColumnName("values"); + + b.HasKey("ItemXItemEffectId") + .HasName("pk_wow_item_effect"); + + b.ToTable("wow_item_effect", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemEffectV2", b => + { + b.Property("ItemId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("item_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ItemId")); + + b.PrimitiveCollection>("ItemEffectIds") + .HasColumnType("integer[]") + .HasColumnName("item_effect_ids"); + + b.Property>>("SpellEffects") + .HasColumnType("jsonb") + .HasColumnName("spell_effects"); + + b.HasKey("ItemId") + .HasName("pk_wow_item_effect_v2"); + + b.ToTable("wow_item_effect_v2", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemModifiedAppearance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AppearanceId") + .HasColumnType("integer") + .HasColumnName("appearance_id"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("Modifier") + .HasColumnType("smallint") + .HasColumnName("modifier"); + + b.Property("Order") + .HasColumnType("smallint") + .HasColumnName("order"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.HasKey("Id") + .HasName("pk_wow_item_modified_appearance"); + + b.ToTable("wow_item_modified_appearance", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowItemSubclass", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuctionHouseSortOrder") + .HasColumnType("smallint") + .HasColumnName("auction_house_sort_order"); + + b.Property("ClassId") + .HasColumnType("smallint") + .HasColumnName("class_id"); + + b.Property("SubclassId") + .HasColumnType("smallint") + .HasColumnName("subclass_id"); + + b.HasKey("Id") + .HasName("pk_wow_item_subclass"); + + b.ToTable("wow_item_subclass", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowJournalInstance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.Property("MapId") + .HasColumnType("smallint") + .HasColumnName("map_id"); + + b.HasKey("Id") + .HasName("pk_wow_journal_instance"); + + b.ToTable("wow_journal_instance", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowMount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.PrimitiveCollection>("ItemIds") + .HasColumnType("integer[]") + .HasColumnName("item_ids"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.Property("SpellId") + .HasColumnType("integer") + .HasColumnName("spell_id"); + + b.HasKey("Id") + .HasName("pk_wow_mount"); + + b.ToTable("wow_mount", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowMythicPlusSeason", b => + { + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.HasKey("Region", "Id") + .HasName("pk_wow_mythic_plus_season"); + + b.ToTable("wow_mythic_plus_season", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowPeriod", b => + { + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Ends") + .HasColumnType("timestamp with time zone") + .HasColumnName("ends"); + + b.Property("Starts") + .HasColumnType("timestamp with time zone") + .HasColumnName("starts"); + + b.HasKey("Region", "Id") + .HasName("pk_wow_period"); + + b.ToTable("wow_period", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowPet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatureId") + .HasColumnType("integer") + .HasColumnName("creature_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.PrimitiveCollection>("ItemIds") + .HasColumnType("integer[]") + .HasColumnName("item_ids"); + + b.Property("PetType") + .HasColumnType("smallint") + .HasColumnName("pet_type"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.Property("SpellId") + .HasColumnType("integer") + .HasColumnName("spell_id"); + + b.HasKey("Id") + .HasName("pk_wow_pet"); + + b.ToTable("wow_pet", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowProfessionRecipeItem", b => + { + b.Property("SkillLineAbilityId") + .HasColumnType("integer") + .HasColumnName("skill_line_ability_id"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("SkillLineId") + .HasColumnType("integer") + .HasColumnName("skill_line_id"); + + b.HasKey("SkillLineAbilityId", "ItemId") + .HasName("pk_wow_profession_recipe_item"); + + b.ToTable("wow_profession_recipe_item", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowQuest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AreaId") + .HasColumnType("integer") + .HasColumnName("area_id"); + + b.Property("CategoryId") + .HasColumnType("integer") + .HasColumnName("category_id"); + + b.Property("LastApiCheck") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_api_check"); + + b.Property("MaximumLevel") + .HasColumnType("smallint") + .HasColumnName("maximum_level"); + + b.Property("MinimumLevel") + .HasColumnType("smallint") + .HasColumnName("minimum_level"); + + b.HasKey("Id") + .HasName("pk_wow_quest"); + + b.ToTable("wow_quest", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowQuestLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.PrimitiveCollection>("QuestIds") + .HasColumnType("integer[]") + .HasColumnName("quest_ids"); + + b.HasKey("Id") + .HasName("pk_wow_quest_line"); + + b.ToTable("wow_quest_line", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowRealm", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("ConnectedRealmId") + .HasColumnType("integer") + .HasColumnName("connected_realm_id"); + + b.Property("EnglishName") + .HasColumnType("text") + .HasColumnName("english_name"); + + b.Property("Locale") + .HasColumnType("text") + .HasColumnName("locale"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Region") + .HasColumnType("integer") + .HasColumnName("region"); + + b.Property("Slug") + .HasColumnType("text") + .HasColumnName("slug"); + + b.HasKey("Id") + .HasName("pk_wow_realm"); + + b.ToTable("wow_realm", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowReputation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountWide") + .HasColumnType("boolean") + .HasColumnName("account_wide"); + + b.PrimitiveCollection>("BaseValues") + .HasColumnType("integer[]") + .HasColumnName("base_values"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.PrimitiveCollection>("MaxValues") + .HasColumnType("integer[]") + .HasColumnName("max_values"); + + b.Property("ParagonId") + .HasColumnType("smallint") + .HasColumnName("paragon_id"); + + b.Property("ParagonQuestId") + .HasColumnType("integer") + .HasColumnName("paragon_quest_id"); + + b.Property("ParagonThreshold") + .HasColumnType("integer") + .HasColumnName("paragon_threshold"); + + b.Property("ParentId") + .HasColumnType("smallint") + .HasColumnName("parent_id"); + + b.Property("RenownCurrencyId") + .HasColumnType("smallint") + .HasColumnName("renown_currency_id"); + + b.Property("TierId") + .HasColumnType("smallint") + .HasColumnName("tier_id"); + + b.HasKey("Id") + .HasName("pk_wow_reputation"); + + b.ToTable("wow_reputation", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowReputationTier", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.PrimitiveCollection("MinValues") + .HasColumnType("integer[]") + .HasColumnName("min_values"); + + b.HasKey("Id") + .HasName("pk_wow_reputation_tier"); + + b.ToTable("wow_reputation_tier", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowToy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.Property("ItemId") + .HasColumnType("integer") + .HasColumnName("item_id"); + + b.Property("SourceType") + .HasColumnType("smallint") + .HasColumnName("source_type"); + + b.HasKey("Id") + .HasName("pk_wow_toy"); + + b.ToTable("wow_toy", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowTransmogSet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClassMask") + .HasColumnType("integer") + .HasColumnName("class_mask"); + + b.Property("Flags") + .HasColumnType("smallint") + .HasColumnName("flags"); + + b.Property("GroupId") + .HasColumnType("smallint") + .HasColumnName("group_id"); + + b.PrimitiveCollection>("ItemModifiedAppearanceIds") + .HasColumnType("integer[]") + .HasColumnName("item_modified_appearance_ids"); + + b.Property("ItemNameDescriptionId") + .HasColumnType("integer") + .HasColumnName("item_name_description_id"); + + b.HasKey("Id") + .HasName("pk_wow_transmog_set"); + + b.ToTable("wow_transmog_set", (string)null); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Wow.WowWorldQuest", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("Expansion") + .HasColumnType("smallint") + .HasColumnName("expansion"); + + b.Property("Faction") + .HasColumnType("smallint") + .HasColumnName("faction"); + + b.Property("MaxLevel") + .HasColumnType("smallint") + .HasColumnName("max_level"); + + b.Property("MinLevel") + .HasColumnType("smallint") + .HasColumnName("min_level"); + + b.PrimitiveCollection>("NeedQuestIds") + .HasColumnType("integer[]") + .HasColumnName("need_quest_ids"); + + b.Property("QuestInfoId") + .HasColumnType("smallint") + .HasColumnName("quest_info_id"); + + b.PrimitiveCollection>("SkipQuestIds") + .HasColumnType("integer[]") + .HasColumnName("skip_quest_ids"); + + b.HasKey("Id") + .HasName("pk_wow_world_quest"); + + b.ToTable("wow_world_quest", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_role_claims_asp_net_roles_role_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_claims_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_logins_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_roles_asp_net_roles_role_id"); + + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_roles_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_asp_net_user_tokens_asp_net_users_user_id"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.BackgroundImage", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", "Role") + .WithMany() + .HasForeignKey("RoleId") + .HasConstraintName("fk_background_image_roles_role_id"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.MiscReport", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_misc_report_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccount", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_player_account_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAchievements", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_achievements_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAddonData", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("AddonData") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountAddonData", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_addon_data_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountGoldSnapshot", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_gold_snapshot_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountHeirlooms", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Heirlooms") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountHeirlooms", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_heirlooms_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountMounts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Mounts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountMounts", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_mounts_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountPets", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Pets") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountPets", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_pets_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountToys", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("Toys") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountToys", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_toys_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogIds", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("TransmogIds") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountTransmogIds", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_transmog_ids_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountTransmogSources", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithOne("TransmogSources") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerAccountTransmogSources", "AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_transmog_sources_player_account_account_id"); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacter", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithMany("Characters") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_player_character_player_account_account_id"); + + b.HasOne("Wowthing.Lib.Models.Player.PlayerGuild", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .HasConstraintName("fk_player_character_player_guild_guild_id"); + + b.Navigation("Account"); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAchievements", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Achievements") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAchievements", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_achievements_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonAchievements", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonAchievements") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonAchievements", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_achievements_player_character_charac"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonData", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonData") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonData", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_data_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonMounts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonMounts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonMounts", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_mounts_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterAddonQuests", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("AddonQuests") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterAddonQuests", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_addon_quests_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterConfiguration", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Configuration") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterConfiguration", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_configuration_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterEquippedItems", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("EquippedItems") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterEquippedItems", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_equipped_items_player_character_character_"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterItem", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany("Items") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_item_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterLockouts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Lockouts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterLockouts", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_lockouts_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMedia", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Media") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMedia", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_media_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMounts", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Mounts") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMounts", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mounts_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlus", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("MythicPlus") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlus", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mythic_plus_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusAddon", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("MythicPlusAddon") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusAddon", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mythic_plus_addon_player_character_charact"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterMythicPlusSeason", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany("MythicPlusSeasons") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_mythic_plus_season_player_character_charac"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterProfessions", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Professions") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterProfessions", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_professions_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterQuests", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Quests") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterQuests", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_quests_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterRaiderIo", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("RaiderIo") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterRaiderIo", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_raider_io_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterReputations", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Reputations") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterReputations", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_reputations_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterShadowlands", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Shadowlands") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterShadowlands", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_shadowlands_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterSpecializations", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Specializations") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterSpecializations", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_specializations_player_character_character"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStatistics", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_statistics_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterStats", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Stats") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterStats", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_stats_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterTransmog", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Transmog") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterTransmog", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_transmog_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacterWeekly", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithOne("Weekly") + .HasForeignKey("Wowthing.Lib.Models.Player.PlayerCharacterWeekly", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_character_weekly_player_character_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuild", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_guild_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuildItem", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerGuild", "Guild") + .WithMany("Items") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_guild_item_player_guild_guild_id"); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerWarbankItem", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_warbank_item_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.Team", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_team_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.TeamCharacter", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerCharacter", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_team_character_player_character_character_id"); + + b.HasOne("Wowthing.Lib.Models.Team.Team", "Team") + .WithMany("Characters") + .HasForeignKey("TeamId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_team_character_team_team_id"); + + b.Navigation("Character"); + + b.Navigation("Team"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserAddonData", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_addon_data_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserBulkData", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_bulk_data_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserCache", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_cache_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserGoldSnapshot", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_user_gold_snapshot_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.User.UserLeaderboardSnapshot", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_leaderboard_snapshot_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.WorldQuestReport", b => + { + b.HasOne("Wowthing.Lib.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_world_quest_report_application_user_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccount", b => + { + b.Navigation("AddonData"); + + b.Navigation("Characters"); + + b.Navigation("Heirlooms"); + + b.Navigation("Mounts"); + + b.Navigation("Pets"); + + b.Navigation("Toys"); + + b.Navigation("TransmogIds"); + + b.Navigation("TransmogSources"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerCharacter", b => + { + b.Navigation("Achievements"); + + b.Navigation("AddonAchievements"); + + b.Navigation("AddonData"); + + b.Navigation("AddonMounts"); + + b.Navigation("AddonQuests"); + + b.Navigation("Configuration"); + + b.Navigation("EquippedItems"); + + b.Navigation("Items"); + + b.Navigation("Lockouts"); + + b.Navigation("Media"); + + b.Navigation("Mounts"); + + b.Navigation("MythicPlus"); + + b.Navigation("MythicPlusAddon"); + + b.Navigation("MythicPlusSeasons"); + + b.Navigation("Professions"); + + b.Navigation("Quests"); + + b.Navigation("RaiderIo"); + + b.Navigation("Reputations"); + + b.Navigation("Shadowlands"); + + b.Navigation("Specializations"); + + b.Navigation("Stats"); + + b.Navigation("Transmog"); + + b.Navigation("Weekly"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerGuild", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Wowthing.Lib.Models.Team.Team", b => + { + b.Navigation("Characters"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/packages/csharp-lib/Migrations/20260704214654_Add_PlayerCharacterAchievements_CompressedCriteriaIds.cs b/packages/csharp-lib/Migrations/20260704214654_Add_PlayerCharacterAchievements_CompressedCriteriaIds.cs new file mode 100644 index 000000000..a8ff60e0b --- /dev/null +++ b/packages/csharp-lib/Migrations/20260704214654_Add_PlayerCharacterAchievements_CompressedCriteriaIds.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Wowthing.Lib.Migrations +{ + /// + public partial class Add_PlayerCharacterAchievements_CompressedCriteriaIds : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "achievement_ids", + table: "player_character_achievements"); + + migrationBuilder.DropColumn( + name: "achievement_timestamps", + table: "player_character_achievements"); + + migrationBuilder.AddColumn( + name: "compressed_criteria_ids", + table: "player_character_achievements", + type: "bytea", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "compressed_criteria_ids", + table: "player_character_achievements"); + + migrationBuilder.AddColumn>( + name: "achievement_ids", + table: "player_character_achievements", + type: "integer[]", + nullable: true); + + migrationBuilder.AddColumn>( + name: "achievement_timestamps", + table: "player_character_achievements", + type: "integer[]", + nullable: true); + } + } +} diff --git a/packages/csharp-lib/Migrations/WowDbContextModelSnapshot.cs b/packages/csharp-lib/Migrations/WowDbContextModelSnapshot.cs index 839e6437b..3c3b7880a 100644 --- a/packages/csharp-lib/Migrations/WowDbContextModelSnapshot.cs +++ b/packages/csharp-lib/Migrations/WowDbContextModelSnapshot.cs @@ -569,6 +569,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("player_account", (string)null); }); + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAchievements", b => + { + b.Property("AccountId") + .HasColumnType("integer") + .HasColumnName("account_id"); + + b.PrimitiveCollection>("AchievementTimestamps") + .HasColumnType("integer[]") + .HasColumnName("achievement_timestamps"); + + b.Property("CompressedAchievementIds") + .HasColumnType("bytea") + .HasColumnName("compressed_achievement_ids"); + + b.HasKey("AccountId") + .HasName("pk_player_account_achievements"); + + b.ToTable("player_account_achievements", (string)null); + }); + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAddonData", b => { b.Property("AccountId") @@ -902,13 +922,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("integer") .HasColumnName("character_id"); - b.PrimitiveCollection>("AchievementIds") - .HasColumnType("integer[]") - .HasColumnName("achievement_ids"); - - b.PrimitiveCollection>("AchievementTimestamps") - .HasColumnType("integer[]") - .HasColumnName("achievement_timestamps"); + b.Property("CompressedCriteriaIds") + .HasColumnType("bytea") + .HasColumnName("compressed_criteria_ids"); b.PrimitiveCollection>("CriteriaAmounts") .HasColumnType("bigint[]") @@ -3895,6 +3911,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAchievements", b => + { + b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") + .WithMany() + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_player_account_achievements_player_account_account_id"); + + b.Navigation("Account"); + }); + modelBuilder.Entity("Wowthing.Lib.Models.Player.PlayerAccountAddonData", b => { b.HasOne("Wowthing.Lib.Models.Player.PlayerAccount", "Account") diff --git a/packages/csharp-lib/Models/Player/PlayerAccountAchievements.cs b/packages/csharp-lib/Models/Player/PlayerAccountAchievements.cs new file mode 100644 index 000000000..be299d92d --- /dev/null +++ b/packages/csharp-lib/Models/Player/PlayerAccountAchievements.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Wowthing.Lib.Models.Player; + +public class PlayerAccountAchievements +{ + [Key, ForeignKey("Account")] + public int AccountId { get; set; } + public PlayerAccount Account { get; set; } + + public byte[] CompressedAchievementIds { get; set; } + public List AchievementTimestamps { get; set; } +} diff --git a/packages/csharp-lib/Models/Player/PlayerCharacterAchievements.cs b/packages/csharp-lib/Models/Player/PlayerCharacterAchievements.cs index 2c7361f29..5bf6a704b 100644 --- a/packages/csharp-lib/Models/Player/PlayerCharacterAchievements.cs +++ b/packages/csharp-lib/Models/Player/PlayerCharacterAchievements.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Wowthing.Lib.Utilities; namespace Wowthing.Lib.Models.Player; @@ -8,10 +9,14 @@ public class PlayerCharacterAchievements [Key, ForeignKey("Character")] public int CharacterId { get; set; } public PlayerCharacter Character { get; set; } - - public List AchievementIds { get; set; } - public List AchievementTimestamps { get; set; } + + public byte[] CompressedCriteriaIds { get; set; } public List CriteriaIds { get; set; } public List CriteriaAmounts { get; set; } public List CriteriaCompleted { get; set; } -} \ No newline at end of file + + [NotMapped] + public List UsableCriteriaIds => CompressedCriteriaIds != null + ? SerializationUtilities.DeserializeFromBitmap(CompressedCriteriaIds) + : CriteriaIds; +} diff --git a/packages/csharp-lib/Models/Query/CompletedAchievementsQuery.cs b/packages/csharp-lib/Models/Query/CompletedAchievementsQuery.cs index 1a879ca9a..1eb33392c 100644 --- a/packages/csharp-lib/Models/Query/CompletedAchievementsQuery.cs +++ b/packages/csharp-lib/Models/Query/CompletedAchievementsQuery.cs @@ -5,17 +5,16 @@ public class CompletedAchievementsQuery { public int AchievementId { get; set; } public int Timestamp { get; set; } - + public static string UserQuery = @" SELECT achievement_id, MIN(timestamp) AS timestamp FROM ( - SELECT UNNEST(pca.achievement_ids) AS achievement_id, - UNNEST(pca.achievement_timestamps) AS timestamp - FROM player_character_achievements pca - LEFT JOIN player_character pc ON pc.id = pca.character_id - LEFT JOIN player_account pa ON pa.id = pc.account_id + SELECT UNNEST(paa.achievement_ids) AS achievement_id, + UNNEST(paa.achievement_timestamps) AS timestamp + FROM player_account_achievements paa + LEFT JOIN player_account pa ON pa.id = paa.account_id WHERE pa.user_id = {0} ) oof GROUP BY achievement_id "; -} \ No newline at end of file +} diff --git a/packages/csharp-lib/Services/CacheService.cs b/packages/csharp-lib/Services/CacheService.cs index 94d735a97..b407e704f 100644 --- a/packages/csharp-lib/Services/CacheService.cs +++ b/packages/csharp-lib/Services/CacheService.cs @@ -136,62 +136,72 @@ long userId { var criteriaCache = await GetCriteriaCacheAsync(db); - var achievementsCompleted = await context.CompletedAchievementsQuery - .FromSqlRaw(CompletedAchievementsQuery.UserQuery, userId) - .ToDictionaryAsync( - caq => caq.AchievementId, - caq => caq.Timestamp - ); + var userAccountAchievements = await context.PlayerAccountAchievements + .AsNoTracking() + .Where(paa => paa.Account.UserId == userId) + .ToArrayAsync(); + + var achievementsCompleted = new Dictionary(); + foreach (var accountAchievements in userAccountAchievements) + { + var achievementIds = SerializationUtilities.DeserializeFromBitmap(accountAchievements.CompressedAchievementIds); + for (int i = 0; i < achievementIds.Count; i++) + { + int achievementId = achievementIds[i]; + int achievementTimestamp = accountAchievements.AchievementTimestamps[i]; + + if (!achievementsCompleted.TryGetValue(achievementId, out int currentTimestamp) || + currentTimestamp > achievementTimestamp) + { + achievementsCompleted[achievementId] = achievementTimestamp; + } + } + } timer.AddPoint("Achievements"); - var criterias = await context.PlayerCharacterAchievements + var userCharacterAchievements = await context.PlayerCharacterAchievements .AsNoTracking() .Where(pca => pca.Character.Account.UserId == userId) - .Select(pca => new - { - pca.CharacterId, - pca.CriteriaAmounts, - pca.CriteriaIds, - }) .ToArrayAsync(); timer.AddPoint("Criteria1b"); var groupedCriteria = new Dictionary>>(); - foreach (var characterCriteria in criterias.EmptyIfNull()) + foreach (var characterAchievements in userCharacterAchievements.EmptyIfNull()) { - if (characterCriteria.CriteriaAmounts == null || characterCriteria.CriteriaIds == null) + var criteriaIds = characterAchievements.UsableCriteriaIds; + if (characterAchievements.CriteriaAmounts == null || criteriaIds == null) { continue; } - for (int i = 0; i < characterCriteria.CriteriaIds.Count; i++) + for (int i = 0; i < criteriaIds.Count; i++) { - int criteriaAmount = (int)characterCriteria.CriteriaAmounts[i]; + int criteriaAmount = (int)characterAchievements.CriteriaAmounts[i]; if (criteriaAmount == 0) { continue; } - int criteriaId = characterCriteria.CriteriaIds[i]; - if (!groupedCriteria.ContainsKey(criteriaId)) + int criteriaId = criteriaIds[i]; + if (!groupedCriteria.TryGetValue(criteriaId, out var criteriaData)) { - groupedCriteria[criteriaId] = new(); + criteriaData = groupedCriteria[criteriaId] = new(); } - if (!groupedCriteria[criteriaId].ContainsKey(criteriaAmount)) + if (!criteriaData.TryGetValue(criteriaAmount, out var amountData)) { - groupedCriteria[criteriaId][criteriaAmount] = new(); + amountData = criteriaData[criteriaAmount] = new(); } - groupedCriteria[criteriaId][criteriaAmount].Add(characterCriteria.CharacterId); + amountData.Add(characterAchievements.CharacterId); } } timer.AddPoint("Criteria2b"); - foreach (var (criteriaId, amounts) in groupedCriteria) + foreach ((int criteriaId, var amounts) in groupedCriteria) { if (!criteriaCache.Character.Contains(criteriaId)) { @@ -235,8 +245,7 @@ long userId Achievements = achievementsCompleted, AddonAchievements = addonAchievements, RawCriteria = groupedCriteria, - Statistics = statistics - .ToGroupedDictionary(stat => stat.StatisticId), + Statistics = statistics.ToGroupedDictionary(stat => stat.StatisticId), }, _jsonSerializerOptions); timer.AddPoint("JSON", true);