From 61176d81f683a2a4a69d2abe9877f7351ba33f38 Mon Sep 17 00:00:00 2001
From: Jay Malhotra <5047192+SapiensAnatis@users.noreply.github.com>
Date: Sun, 16 Jul 2023 16:54:32 +0100
Subject: [PATCH] Add 'preferred team' feature (#307)
Implements:
- /quest/get_quest_clear_party
- /quest/get_quest_clear_party_multi
- /quest/set_quest_clear_party
- /quest/set_quest_clear_party_multi
Includes a new database table for saved clear units, and also logic to
detect when entities from saved parties are missing.
Saved clear parties are exempted from the save import deletion process,
as they are not contained in a save, so wiping them on every import
seemed harsh. As a result, they may contain entities which the user no
longer owns.
Fortunately, the game provides a mechanism to handle this in the form of
"lost_unit_list", which shows a pop-up indicating what entities cannot
be retrieved from the clear party.
This is probably intended for entities which can normally be lost, like
dragons or portrait prints, but seems to work sort of okay with weapons
and wyrmprints:
There is however no entity type for missing shared skills, and missing
characters will cause the button to be disabled entirely.
---
DragaliaAPI.Database/ApiContext.cs | 2 +
.../Entities/Abstract/DbPartyUnitBase.cs | 17 +
.../Entities/Abstract/DbUnitBase.cs | 31 +
DragaliaAPI.Database/Entities/DbPartyUnit.cs | 33 +-
.../Entities/DbQuestClearPartyUnit.cs | 53 +
DragaliaAPI.Database/Entities/DbSetUnit.cs | 28 +-
.../Entities/Scaffold/DbDetailedPartyUnit.cs | 6 +-
...0715142823_quest-clear-parties.Designer.cs | 1772 ++++++++++++++++
.../20230715142823_quest-clear-parties.cs | 56 +
...15171619_quest-clear-parties-2.Designer.cs | 1778 +++++++++++++++++
.../20230715171619_quest-clear-parties-2.cs | 40 +
.../Migrations/ApiContextModelSnapshot.cs | 92 +-
.../CustomWebApplicationFactory.cs | 3 +-
.../Dragalia/QuestClearPartyTest.cs | 474 +++++
.../{QuestTest.cs => QuestReadStoryTest.cs} | 12 +-
DragaliaAPI.Integration.Test/TestFixture.cs | 2 +
.../Definitions/Enums/AbilityCrests.cs | 1 +
.../Definitions/Enums/Dragons.cs | 1 +
.../Definitions/Enums/Talismans.cs | 1 +
.../Controllers/QuestControllerTest.cs | 5 +
.../AutoMapper/Profiles/UnitMapProfile.cs | 7 +
.../Profiles/UnitReverseMapProfile.cs | 7 +
.../Dragalia/MatchingController.cs | 3 +-
.../Controllers/Dragalia/QuestController.cs | 205 --
.../Controllers/Dragalia/SummonController.cs | 2 +-
.../Extensions/IEnumerableExtensions.cs | 5 +-
.../ClearParty/ClearPartyRepository.cs | 45 +
.../Features/ClearParty/ClearPartyService.cs | 352 ++++
.../ClearParty/IClearPartyRepository.cs | 11 +
.../Features/ClearParty/IClearPartyService.cs | 12 +
.../Features/Dungeon/DungeonRepository.cs | 140 +-
.../Features/Dungeon/IDungeonRepository.cs | 3 +
DragaliaAPI/Features/Quest/QuestController.cs | 162 ++
DragaliaAPI/Models/Generated/Components.cs | 66 +-
DragaliaAPI/Program.cs | 6 +-
.../Services/Photon/HeroParamService.cs | 4 -
36 files changed, 5119 insertions(+), 318 deletions(-)
create mode 100644 DragaliaAPI.Database/Entities/Abstract/DbPartyUnitBase.cs
create mode 100644 DragaliaAPI.Database/Entities/Abstract/DbUnitBase.cs
create mode 100644 DragaliaAPI.Database/Entities/DbQuestClearPartyUnit.cs
create mode 100644 DragaliaAPI.Database/Migrations/20230715142823_quest-clear-parties.Designer.cs
create mode 100644 DragaliaAPI.Database/Migrations/20230715142823_quest-clear-parties.cs
create mode 100644 DragaliaAPI.Database/Migrations/20230715171619_quest-clear-parties-2.Designer.cs
create mode 100644 DragaliaAPI.Database/Migrations/20230715171619_quest-clear-parties-2.cs
create mode 100644 DragaliaAPI.Integration.Test/Dragalia/QuestClearPartyTest.cs
rename DragaliaAPI.Integration.Test/Dragalia/{QuestTest.cs => QuestReadStoryTest.cs} (87%)
delete mode 100644 DragaliaAPI/Controllers/Dragalia/QuestController.cs
create mode 100644 DragaliaAPI/Features/ClearParty/ClearPartyRepository.cs
create mode 100644 DragaliaAPI/Features/ClearParty/ClearPartyService.cs
create mode 100644 DragaliaAPI/Features/ClearParty/IClearPartyRepository.cs
create mode 100644 DragaliaAPI/Features/ClearParty/IClearPartyService.cs
create mode 100644 DragaliaAPI/Features/Quest/QuestController.cs
diff --git a/DragaliaAPI.Database/ApiContext.cs b/DragaliaAPI.Database/ApiContext.cs
index 0ac319b6a..e9d600703 100644
--- a/DragaliaAPI.Database/ApiContext.cs
+++ b/DragaliaAPI.Database/ApiContext.cs
@@ -155,4 +155,6 @@ but EF Core doesn't like this and the client probably stops you anyway?
public DbSet PlayerPurchases { get; set; }
public DbSet PlayerTrades { get; set; }
+
+ public DbSet QuestClearPartyUnits { get; set; }
}
diff --git a/DragaliaAPI.Database/Entities/Abstract/DbPartyUnitBase.cs b/DragaliaAPI.Database/Entities/Abstract/DbPartyUnitBase.cs
new file mode 100644
index 000000000..bbd16ae3f
--- /dev/null
+++ b/DragaliaAPI.Database/Entities/Abstract/DbPartyUnitBase.cs
@@ -0,0 +1,17 @@
+using DragaliaAPI.Shared.Definitions.Enums;
+
+namespace DragaliaAPI.Database.Entities.Abstract;
+
+///
+/// Base class for party units with edit skills / weapon skins equipped.
+///
+public abstract class DbPartyUnitBase : DbUnitBase
+{
+ public int EquipWeaponSkinId { get; set; }
+
+ public Charas EditSkill1CharaId { get; set; }
+
+ public Charas EditSkill2CharaId { get; set; }
+
+ public required int UnitNo { get; set; }
+}
diff --git a/DragaliaAPI.Database/Entities/Abstract/DbUnitBase.cs b/DragaliaAPI.Database/Entities/Abstract/DbUnitBase.cs
new file mode 100644
index 000000000..130aa2645
--- /dev/null
+++ b/DragaliaAPI.Database/Entities/Abstract/DbUnitBase.cs
@@ -0,0 +1,31 @@
+using DragaliaAPI.Shared.Definitions.Enums;
+
+namespace DragaliaAPI.Database.Entities.Abstract;
+
+///
+/// Base class for party units and unit equipment set entries.
+///
+public abstract class DbUnitBase
+{
+ public Charas CharaId { get; set; }
+
+ public long EquipDragonKeyId { get; set; }
+
+ public WeaponBodies EquipWeaponBodyId { get; set; }
+
+ public AbilityCrests EquipCrestSlotType1CrestId1 { get; set; }
+
+ public AbilityCrests EquipCrestSlotType1CrestId2 { get; set; }
+
+ public AbilityCrests EquipCrestSlotType1CrestId3 { get; set; }
+
+ public AbilityCrests EquipCrestSlotType2CrestId1 { get; set; }
+
+ public AbilityCrests EquipCrestSlotType2CrestId2 { get; set; }
+
+ public AbilityCrests EquipCrestSlotType3CrestId1 { get; set; }
+
+ public AbilityCrests EquipCrestSlotType3CrestId2 { get; set; }
+
+ public long EquipTalismanKeyId { get; set; }
+}
diff --git a/DragaliaAPI.Database/Entities/DbPartyUnit.cs b/DragaliaAPI.Database/Entities/DbPartyUnit.cs
index ea6dc73d3..a5366877b 100644
--- a/DragaliaAPI.Database/Entities/DbPartyUnit.cs
+++ b/DragaliaAPI.Database/Entities/DbPartyUnit.cs
@@ -1,12 +1,13 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
+using DragaliaAPI.Database.Entities.Abstract;
using DragaliaAPI.Shared.Definitions.Enums;
using Microsoft.EntityFrameworkCore;
namespace DragaliaAPI.Database.Entities;
[Index(nameof(DeviceAccountId))]
-public class DbPartyUnit
+public class DbPartyUnit : DbPartyUnitBase
{
// In theory, a composite primary key of [Party, UnitNo] would work great.
// However, EF Core doesn't like navigation properties being used as keys.
@@ -19,34 +20,4 @@ public class DbPartyUnit
public string DeviceAccountId { get; set; } = string.Empty;
public int PartyNo { get; set; }
-
- public required int UnitNo { get; set; }
-
- public required Charas CharaId { get; set; }
-
- public long EquipDragonKeyId { get; set; } = 0;
-
- public WeaponBodies EquipWeaponBodyId { get; set; }
-
- public int EquipWeaponSkinId { get; set; }
-
- public AbilityCrests EquipCrestSlotType1CrestId1 { get; set; }
-
- public AbilityCrests EquipCrestSlotType1CrestId2 { get; set; }
-
- public AbilityCrests EquipCrestSlotType1CrestId3 { get; set; }
-
- public AbilityCrests EquipCrestSlotType2CrestId1 { get; set; }
-
- public AbilityCrests EquipCrestSlotType2CrestId2 { get; set; }
-
- public AbilityCrests EquipCrestSlotType3CrestId1 { get; set; }
-
- public AbilityCrests EquipCrestSlotType3CrestId2 { get; set; }
-
- public long EquipTalismanKeyId { get; set; }
-
- public Charas EditSkill1CharaId { get; set; }
-
- public Charas EditSkill2CharaId { get; set; }
}
diff --git a/DragaliaAPI.Database/Entities/DbQuestClearPartyUnit.cs b/DragaliaAPI.Database/Entities/DbQuestClearPartyUnit.cs
new file mode 100644
index 000000000..72efc319c
--- /dev/null
+++ b/DragaliaAPI.Database/Entities/DbQuestClearPartyUnit.cs
@@ -0,0 +1,53 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using DragaliaAPI.Database.Entities.Abstract;
+using DragaliaAPI.Shared.Definitions.Enums;
+using Microsoft.EntityFrameworkCore;
+
+namespace DragaliaAPI.Database.Entities;
+
+[PrimaryKey(nameof(DeviceAccountId), nameof(QuestId), nameof(IsMulti), nameof(UnitNo))]
+public class DbQuestClearPartyUnit : DbPartyUnitBase, IDbHasAccountId
+{
+ public virtual DbPlayer? Owner { get; set; }
+
+ [ForeignKey(nameof(Owner))]
+ public required string DeviceAccountId { get; set; }
+
+ public required int QuestId { get; set; }
+
+ public required bool IsMulti { get; set; }
+
+ public Dragons EquippedDragonEntityId { get; set; }
+
+ public Talismans EquippedTalismanEntityId { get; set; }
+
+ ///
+ /// Reset this entity back to a state representing an empty slot.
+ ///
+ public void Clear()
+ {
+ this.CharaId = Charas.Empty;
+
+ this.EquipWeaponBodyId = WeaponBodies.Empty;
+ this.EquipWeaponSkinId = 0;
+
+ this.EquipDragonKeyId = 0;
+ this.EquipTalismanKeyId = 0;
+ this.EquippedDragonEntityId = Dragons.Empty;
+ this.EquippedTalismanEntityId = Talismans.Empty;
+
+ this.EquipCrestSlotType1CrestId1 = AbilityCrests.Empty;
+ this.EquipCrestSlotType1CrestId2 = AbilityCrests.Empty;
+ this.EquipCrestSlotType1CrestId3 = AbilityCrests.Empty;
+
+ this.EquipCrestSlotType2CrestId1 = AbilityCrests.Empty;
+ this.EquipCrestSlotType2CrestId2 = AbilityCrests.Empty;
+
+ this.EquipCrestSlotType3CrestId1 = AbilityCrests.Empty;
+ this.EquipCrestSlotType3CrestId2 = AbilityCrests.Empty;
+
+ this.EditSkill1CharaId = Charas.Empty;
+ this.EditSkill2CharaId = Charas.Empty;
+ }
+}
diff --git a/DragaliaAPI.Database/Entities/DbSetUnit.cs b/DragaliaAPI.Database/Entities/DbSetUnit.cs
index 250a7b072..7819f8049 100644
--- a/DragaliaAPI.Database/Entities/DbSetUnit.cs
+++ b/DragaliaAPI.Database/Entities/DbSetUnit.cs
@@ -1,47 +1,23 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
+using DragaliaAPI.Database.Entities.Abstract;
using DragaliaAPI.Shared.Definitions.Enums;
using Microsoft.EntityFrameworkCore;
namespace DragaliaAPI.Database.Entities;
-//TODO: This and PartyUnit share a lot of properties, maybe extract those and make these into subclasses which inherit them
[Table("PlayerSetUnit")]
[Index(nameof(DeviceAccountId))]
-public class DbSetUnit : IDbHasAccountId
+public class DbSetUnit : DbUnitBase, IDbHasAccountId
{
///
public virtual DbPlayer? Owner { get; set; }
- ///
[ForeignKey(nameof(Owner))]
public required string DeviceAccountId { get; set; }
- [Required]
- public Charas CharaId { get; set; }
-
[Required]
public int UnitSetNo { get; set; }
public required string UnitSetName { get; set; }
-
- public long EquipDragonKeyId { get; set; }
-
- public int EquipWeaponBodyId { get; set; }
-
- public int EquipCrestSlotType1CrestId1 { get; set; }
-
- public int EquipCrestSlotType1CrestId2 { get; set; }
-
- public int EquipCrestSlotType1CrestId3 { get; set; }
-
- public int EquipCrestSlotType2CrestId1 { get; set; }
-
- public int EquipCrestSlotType2CrestId2 { get; set; }
-
- public int EquipCrestSlotType3CrestId1 { get; set; }
-
- public int EquipCrestSlotType3CrestId2 { get; set; }
-
- public long EquipTalismanKeyId { get; set; }
}
diff --git a/DragaliaAPI.Database/Entities/Scaffold/DbDetailedPartyUnit.cs b/DragaliaAPI.Database/Entities/Scaffold/DbDetailedPartyUnit.cs
index 3366c9406..0f748f02c 100644
--- a/DragaliaAPI.Database/Entities/Scaffold/DbDetailedPartyUnit.cs
+++ b/DragaliaAPI.Database/Entities/Scaffold/DbDetailedPartyUnit.cs
@@ -8,6 +8,8 @@ public class DbDetailedPartyUnit
{
public required string DeviceAccountId { get; set; }
+ public int PartyNo { get; set; }
+
public int Position { get; set; }
public required DbPlayerCharaData CharaData { get; set; }
@@ -21,10 +23,10 @@ public class DbDetailedPartyUnit
public IEnumerable CrestSlotType1CrestList { get; set; } =
Enumerable.Empty();
- public IEnumerable CrestSlotType2CrestList { get; set; } =
+ public IEnumerable CrestSlotType2CrestList { get; set; } =
Enumerable.Empty();
- public IEnumerable CrestSlotType3CrestList { get; set; } =
+ public IEnumerable CrestSlotType3CrestList { get; set; } =
Enumerable.Empty();
public DbWeaponSkin? WeaponSkinData { get; set; } = null;
diff --git a/DragaliaAPI.Database/Migrations/20230715142823_quest-clear-parties.Designer.cs b/DragaliaAPI.Database/Migrations/20230715142823_quest-clear-parties.Designer.cs
new file mode 100644
index 000000000..9b66c1ad6
--- /dev/null
+++ b/DragaliaAPI.Database/Migrations/20230715142823_quest-clear-parties.Designer.cs
@@ -0,0 +1,1772 @@
+//
+using System;
+using DragaliaAPI.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace DragaliaAPI.Database.Migrations
+{
+ [DbContext(typeof(ApiContext))]
+ [Migration("20230715142823_quest-clear-parties")]
+ partial class questclearparties
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.5")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbAbilityCrest", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("AbilityCrestId")
+ .HasColumnType("integer");
+
+ b.Property("AttackPlusCount")
+ .HasColumnType("integer");
+
+ b.Property("BuildupCount")
+ .HasColumnType("integer");
+
+ b.Property("EquipableCount")
+ .HasColumnType("integer");
+
+ b.Property("GetTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("HpPlusCount")
+ .HasColumnType("integer");
+
+ b.Property("IsFavorite")
+ .HasColumnType("boolean");
+
+ b.Property("IsNew")
+ .HasColumnType("boolean");
+
+ b.Property("LimitBreakCount")
+ .HasColumnType("integer");
+
+ b.HasKey("DeviceAccountId", "AbilityCrestId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerAbilityCrests");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbAbilityCrestSet", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("AbilityCrestSetNo")
+ .HasColumnType("integer");
+
+ b.Property("AbilityCrestSetName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("CrestSlotType1CrestId1")
+ .HasColumnType("integer");
+
+ b.Property("CrestSlotType1CrestId2")
+ .HasColumnType("integer");
+
+ b.Property("CrestSlotType1CrestId3")
+ .HasColumnType("integer");
+
+ b.Property("CrestSlotType2CrestId1")
+ .HasColumnType("integer");
+
+ b.Property("CrestSlotType2CrestId2")
+ .HasColumnType("integer");
+
+ b.Property("CrestSlotType3CrestId1")
+ .HasColumnType("integer");
+
+ b.Property("CrestSlotType3CrestId2")
+ .HasColumnType("integer");
+
+ b.Property("TalismanKeyId")
+ .HasColumnType("numeric(20,0)");
+
+ b.HasKey("DeviceAccountId", "AbilityCrestSetNo");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerAbilityCrestSets");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbDeviceAccount", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("text");
+
+ b.Property("HashedPassword")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("DeviceAccounts");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbEquippedStamp", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("Slot")
+ .HasColumnType("integer");
+
+ b.Property("StampId")
+ .HasColumnType("integer");
+
+ b.HasKey("DeviceAccountId", "Slot");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("EquippedStamps");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbFortBuild", b =>
+ {
+ b.Property("BuildId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("BuildId"));
+
+ b.Property("BuildEndDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("BuildStartDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeviceAccountId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("IsNew")
+ .HasColumnType("boolean");
+
+ b.Property("LastIncomeDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Level")
+ .HasColumnType("integer");
+
+ b.Property("PlantId")
+ .HasColumnType("integer");
+
+ b.Property("PositionX")
+ .HasColumnType("integer");
+
+ b.Property("PositionZ")
+ .HasColumnType("integer");
+
+ b.HasKey("BuildId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerFortBuilds");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbFortDetail", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("CarpenterNum")
+ .HasColumnType("integer")
+ .HasColumnName("CarpenterNum");
+
+ b.HasKey("DeviceAccountId");
+
+ b.HasIndex("DeviceAccountId")
+ .IsUnique();
+
+ b.ToTable("PlayerFortDetail");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbParty", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("PartyNo")
+ .HasColumnType("integer");
+
+ b.Property("PartyName")
+ .IsRequired()
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)");
+
+ b.HasKey("DeviceAccountId", "PartyNo");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PartyData");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPartyUnit", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("text");
+
+ b.Property("CharaId")
+ .HasColumnType("integer");
+
+ b.Property("DeviceAccountId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("EditSkill1CharaId")
+ .HasColumnType("integer");
+
+ b.Property("EditSkill2CharaId")
+ .HasColumnType("integer");
+
+ b.Property("EquipCrestSlotType1CrestId1")
+ .HasColumnType("integer");
+
+ b.Property("EquipCrestSlotType1CrestId2")
+ .HasColumnType("integer");
+
+ b.Property("EquipCrestSlotType1CrestId3")
+ .HasColumnType("integer");
+
+ b.Property("EquipCrestSlotType2CrestId1")
+ .HasColumnType("integer");
+
+ b.Property("EquipCrestSlotType2CrestId2")
+ .HasColumnType("integer");
+
+ b.Property("EquipCrestSlotType3CrestId1")
+ .HasColumnType("integer");
+
+ b.Property("EquipCrestSlotType3CrestId2")
+ .HasColumnType("integer");
+
+ b.Property("EquipDragonKeyId")
+ .HasColumnType("bigint");
+
+ b.Property("EquipTalismanKeyId")
+ .HasColumnType("bigint");
+
+ b.Property("EquipWeaponBodyId")
+ .HasColumnType("integer");
+
+ b.Property("EquipWeaponSkinId")
+ .HasColumnType("integer");
+
+ b.Property("PartyNo")
+ .HasColumnType("integer");
+
+ b.Property("UnitNo")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.HasIndex("DeviceAccountId", "PartyNo");
+
+ b.ToTable("PlayerPartyUnits");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayer", b =>
+ {
+ b.Property("AccountId")
+ .HasColumnType("text");
+
+ b.Property("SavefileVersion")
+ .HasColumnType("integer");
+
+ b.HasKey("AccountId");
+
+ b.ToTable("Players");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerBannerData", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("SummonBannerId")
+ .HasColumnType("integer")
+ .HasColumnName("SummonBannerId");
+
+ b.Property("ConsecutionSummonPoints")
+ .HasColumnType("integer")
+ .HasColumnName("CsSummonPoints");
+
+ b.Property("ConsecutionSummonPointsMaxDate")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("CsSummonPointsMaxDate");
+
+ b.Property("ConsecutionSummonPointsMinDate")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("CsSummonPointsMinDate");
+
+ b.Property("DailyLimitedSummonCount")
+ .HasColumnType("integer")
+ .HasColumnName("DailyLimitedSummons");
+
+ b.Property("IsBeginnerFreeSummonAvailable")
+ .HasColumnType("integer")
+ .HasColumnName("BeginnerSummonAvailable");
+
+ b.Property("IsConsecutionFreeSummonAvailable")
+ .HasColumnType("integer")
+ .HasColumnName("CsSummonAvailable");
+
+ b.Property("IsFreeSummonAvailable")
+ .HasColumnType("integer")
+ .HasColumnName("FreeSummonAvailable");
+
+ b.Property("PityRate")
+ .HasColumnType("smallint")
+ .HasColumnName("Pity");
+
+ b.Property("SummonCount")
+ .HasColumnType("integer")
+ .HasColumnName("SummonCount");
+
+ b.Property("SummonPoints")
+ .HasColumnType("integer")
+ .HasColumnName("SummonPoints");
+
+ b.HasKey("DeviceAccountId", "SummonBannerId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerBannerData");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerCharaData", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("CharaId")
+ .HasColumnType("integer")
+ .HasColumnName("CharaId");
+
+ b.Property("Ability1Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Abil1Lvl");
+
+ b.Property("Ability2Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Abil2Lvl");
+
+ b.Property("Ability3Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Abil3Lvl");
+
+ b.Property("AttackBase")
+ .HasColumnType("integer")
+ .HasColumnName("AtkBase");
+
+ b.Property("AttackNode")
+ .HasColumnType("integer")
+ .HasColumnName("AtkNode");
+
+ b.Property("AttackPlusCount")
+ .HasColumnType("smallint")
+ .HasColumnName("AtkPlusCount");
+
+ b.Property("BurstAttackLevel")
+ .HasColumnType("smallint")
+ .HasColumnName("BurstAtkLvl");
+
+ b.Property("ComboBuildupCount")
+ .HasColumnType("integer")
+ .HasColumnName("ComboBuildupCount");
+
+ b.Property("ExAbility2Level")
+ .HasColumnType("smallint")
+ .HasColumnName("ExAbility2Lvl");
+
+ b.Property("ExAbilityLevel")
+ .HasColumnType("smallint")
+ .HasColumnName("ExAbility1Lvl");
+
+ b.Property("Exp")
+ .HasColumnType("integer")
+ .HasColumnName("Exp");
+
+ b.Property("GetTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("GetTime");
+
+ b.Property("HpBase")
+ .HasColumnType("integer")
+ .HasColumnName("HpBase");
+
+ b.Property("HpNode")
+ .HasColumnType("integer")
+ .HasColumnName("HpNode");
+
+ b.Property("HpPlusCount")
+ .HasColumnType("smallint")
+ .HasColumnName("HpPlusCount");
+
+ b.Property("IsNew")
+ .HasColumnType("boolean")
+ .HasColumnName("IsNew");
+
+ b.Property("IsTemporary")
+ .HasColumnType("boolean")
+ .HasColumnName("IsTemp");
+
+ b.Property("IsUnlockEditSkill")
+ .HasColumnType("boolean")
+ .HasColumnName("IsUnlockEditSkill");
+
+ b.Property("Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Level");
+
+ b.Property("ListViewFlag")
+ .HasColumnType("boolean")
+ .HasColumnName("ListViewFlag");
+
+ b.Property("ManaNodeUnlockCount")
+ .HasColumnType("integer")
+ .HasColumnName("ManaNodeUnlockCount");
+
+ b.Property("Rarity")
+ .HasColumnType("smallint")
+ .HasColumnName("Rarity");
+
+ b.Property("Skill1Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Skill1Lvl");
+
+ b.Property("Skill2Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Skill2Lvl");
+
+ b.HasKey("DeviceAccountId", "CharaId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerCharaData");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerCurrency", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("CurrencyType")
+ .HasColumnType("integer")
+ .HasColumnName("CurrencyType");
+
+ b.Property("Quantity")
+ .HasColumnType("bigint")
+ .HasColumnName("Quantity");
+
+ b.HasKey("DeviceAccountId", "CurrencyType");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerCurrency");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerDragonData", b =>
+ {
+ b.Property("DragonKeyId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("DragonKeyId");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("DragonKeyId"));
+
+ b.Property("Ability1Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Abil1Level");
+
+ b.Property("Ability2Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Abil2Level");
+
+ b.Property("AttackPlusCount")
+ .HasColumnType("smallint")
+ .HasColumnName("AttackPlusCount");
+
+ b.Property("DeviceAccountId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("DragonId")
+ .HasColumnType("integer")
+ .HasColumnName("DragonId");
+
+ b.Property("Exp")
+ .HasColumnType("integer")
+ .HasColumnName("Exp");
+
+ b.Property("GetTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("GetTime");
+
+ b.Property("HpPlusCount")
+ .HasColumnType("smallint")
+ .HasColumnName("HpPlusCount");
+
+ b.Property("IsLock")
+ .HasColumnType("boolean")
+ .HasColumnName("IsLocked");
+
+ b.Property("IsNew")
+ .HasColumnType("boolean")
+ .HasColumnName("IsNew");
+
+ b.Property("Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Level");
+
+ b.Property("LimitBreakCount")
+ .HasColumnType("smallint")
+ .HasColumnName("LimitBreakCount");
+
+ b.Property("Skill1Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Skill1Level");
+
+ b.HasKey("DragonKeyId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerDragonData");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerDragonGift", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text")
+ .HasColumnName("DeviceAccountId");
+
+ b.Property("DragonGiftId")
+ .HasColumnType("integer")
+ .HasColumnName("DragonGiftId");
+
+ b.Property("Quantity")
+ .HasColumnType("integer")
+ .HasColumnName("Quantity");
+
+ b.HasKey("DeviceAccountId", "DragonGiftId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerDragonGift");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerDragonReliability", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("DragonId")
+ .HasColumnType("integer")
+ .HasColumnName("DragonId");
+
+ b.Property("Exp")
+ .HasColumnType("integer")
+ .HasColumnName("TotalExp");
+
+ b.Property("GetTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LastContactTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("LastContactTime");
+
+ b.Property("Level")
+ .HasColumnType("smallint")
+ .HasColumnName("Level");
+
+ b.HasKey("DeviceAccountId", "DragonId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerDragonReliability");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerMaterial", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("MaterialId")
+ .HasColumnType("integer")
+ .HasColumnName("MaterialId");
+
+ b.Property("Quantity")
+ .HasColumnType("integer")
+ .HasColumnName("Quantity");
+
+ b.HasKey("DeviceAccountId", "MaterialId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerMaterial");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerMission", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("Id")
+ .HasColumnType("integer")
+ .HasColumnName("MissionId");
+
+ b.Property("Type")
+ .HasColumnType("integer")
+ .HasColumnName("Type");
+
+ b.Property("End")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("EndDate");
+
+ b.Property("GroupId")
+ .HasColumnType("integer")
+ .HasColumnName("GroupId");
+
+ b.Property("Pickup")
+ .HasColumnType("boolean")
+ .HasColumnName("Pickup");
+
+ b.Property("Progress")
+ .HasColumnType("integer")
+ .HasColumnName("Progress");
+
+ b.Property("Start")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("StartDate");
+
+ b.Property("State")
+ .HasColumnType("integer")
+ .HasColumnName("State");
+
+ b.HasKey("DeviceAccountId", "Id", "Type");
+
+ b.ToTable("PlayerMissions");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerPresent", b =>
+ {
+ b.Property("PresentId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("PresentId");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PresentId"));
+
+ b.Property("CreateTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("CreateTime");
+
+ b.Property("DeviceAccountId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("EntityId")
+ .HasColumnType("integer")
+ .HasColumnName("EntityId");
+
+ b.Property("EntityLevel")
+ .HasColumnType("integer")
+ .HasColumnName("EntityLevel");
+
+ b.Property("EntityLimitBreakCount")
+ .HasColumnType("integer")
+ .HasColumnName("EntityLimitBreakCount");
+
+ b.Property("EntityQuantity")
+ .HasColumnType("integer")
+ .HasColumnName("EntityQuantity");
+
+ b.Property("EntityStatusPlusCount")
+ .HasColumnType("integer")
+ .HasColumnName("EntityStatusPlusCount");
+
+ b.Property("EntityType")
+ .HasColumnType("integer")
+ .HasColumnName("EntityType");
+
+ b.Property("MasterId")
+ .HasColumnType("bigint")
+ .HasColumnName("MasterId");
+
+ b.Property("MessageId")
+ .HasColumnType("integer")
+ .HasColumnName("MessageId");
+
+ b.Property("MessageParamValue1")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue1");
+
+ b.Property("MessageParamValue2")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue2");
+
+ b.Property("MessageParamValue3")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue3");
+
+ b.Property("MessageParamValue4")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue4");
+
+ b.Property("ReceiveLimitTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("ReceiveLimitTime");
+
+ b.Property("State")
+ .HasColumnType("bigint")
+ .HasColumnName("State");
+
+ b.HasKey("PresentId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerPresent");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerPresentHistory", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("bigint");
+
+ b.Property("CreateTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("CreateTime");
+
+ b.Property("DeviceAccountId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("EntityId")
+ .HasColumnType("integer")
+ .HasColumnName("EntityId");
+
+ b.Property("EntityLevel")
+ .HasColumnType("integer")
+ .HasColumnName("EntityLevel");
+
+ b.Property("EntityLimitBreakCount")
+ .HasColumnType("integer")
+ .HasColumnName("EntityLimitBreakCount");
+
+ b.Property("EntityQuantity")
+ .HasColumnType("integer")
+ .HasColumnName("EntityQuantity");
+
+ b.Property("EntityStatusPlusCount")
+ .HasColumnType("integer")
+ .HasColumnName("EntityStatusPlusCount");
+
+ b.Property("EntityType")
+ .HasColumnType("integer")
+ .HasColumnName("EntityType");
+
+ b.Property("MessageId")
+ .HasColumnType("integer")
+ .HasColumnName("MessageId");
+
+ b.Property("MessageParamValue1")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue1");
+
+ b.Property("MessageParamValue2")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue2");
+
+ b.Property("MessageParamValue3")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue3");
+
+ b.Property("MessageParamValue4")
+ .HasColumnType("integer")
+ .HasColumnName("MessageParamValue4");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerPresentHistory");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerShopInfo", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("DailySummonCount")
+ .HasColumnType("integer");
+
+ b.Property("LastSummonTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.HasKey("DeviceAccountId");
+
+ b.ToTable("PlayerShopInfos");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerShopPurchase", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("GoodsId")
+ .HasColumnType("integer");
+
+ b.Property("BuyCount")
+ .HasColumnType("integer");
+
+ b.Property("EffectEndTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EffectStartTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LastBuyTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ShopType")
+ .HasColumnType("integer");
+
+ b.HasKey("DeviceAccountId", "GoodsId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerPurchases");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerStoryState", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("StoryType")
+ .HasColumnType("integer")
+ .HasColumnName("StoryType");
+
+ b.Property("StoryId")
+ .HasColumnType("integer")
+ .HasColumnName("StoryId");
+
+ b.Property("State")
+ .HasColumnType("integer")
+ .HasColumnName("State");
+
+ b.HasKey("DeviceAccountId", "StoryType", "StoryId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerStoryState");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerSummonHistory", b =>
+ {
+ b.Property("KeyId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("KeyId"));
+
+ b.Property("DeviceAccountId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("EntityAttackPlusCount")
+ .HasColumnType("integer")
+ .HasColumnName("AtkPlusCount");
+
+ b.Property("EntityHpPlusCount")
+ .HasColumnType("integer")
+ .HasColumnName("HpPlusCount");
+
+ b.Property("EntityId")
+ .HasColumnType("integer")
+ .HasColumnName("EntityId");
+
+ b.Property("EntityLevel")
+ .HasColumnType("smallint")
+ .HasColumnName("Level");
+
+ b.Property("EntityLimitBreakCount")
+ .HasColumnType("smallint")
+ .HasColumnName("LimitBreakCount");
+
+ b.Property("EntityQuantity")
+ .HasColumnType("integer")
+ .HasColumnName("Quantity");
+
+ b.Property("EntityRarity")
+ .HasColumnType("smallint")
+ .HasColumnName("Rarity");
+
+ b.Property("EntityType")
+ .HasColumnType("integer")
+ .HasColumnName("EntityType");
+
+ b.Property("ExecDate")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("SummonDate");
+
+ b.Property("GetDewPointQuantity")
+ .HasColumnType("integer")
+ .HasColumnName("DewPointGet");
+
+ b.Property("PaymentType")
+ .HasColumnType("integer")
+ .HasColumnName("PaymentType");
+
+ b.Property("SummonExecType")
+ .HasColumnType("smallint")
+ .HasColumnName("SummonExecType");
+
+ b.Property("SummonId")
+ .HasColumnType("integer")
+ .HasColumnName("BannerId");
+
+ b.Property("SummonPoint")
+ .HasColumnType("integer")
+ .HasColumnName("SummonPointGet");
+
+ b.Property("SummonPrizeRank")
+ .HasColumnType("integer")
+ .HasColumnName("SummonPrizeRank");
+
+ b.HasKey("KeyId");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.ToTable("PlayerSummonHistory");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerTrade", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("Id")
+ .HasColumnType("integer")
+ .HasColumnName("TradeId");
+
+ b.Property("Count")
+ .HasColumnType("integer")
+ .HasColumnName("TradeCount");
+
+ b.Property("LastTradeTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("LastTrade");
+
+ b.Property("Type")
+ .HasColumnType("integer")
+ .HasColumnName("TradeType");
+
+ b.HasKey("DeviceAccountId", "Id");
+
+ b.HasIndex("DeviceAccountId");
+
+ b.HasIndex("DeviceAccountId", "Type");
+
+ b.ToTable("PlayerTrades");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbPlayerUserData", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("ActiveMemoryEventId")
+ .HasColumnType("integer");
+
+ b.Property("BuildTimePoint")
+ .HasColumnType("integer");
+
+ b.Property("Coin")
+ .HasColumnType("bigint");
+
+ b.Property("CreateTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Crystal")
+ .HasColumnType("integer");
+
+ b.Property("DewPoint")
+ .HasColumnType("integer");
+
+ b.Property("EmblemId")
+ .HasColumnType("integer");
+
+ b.Property("Exp")
+ .HasColumnType("integer");
+
+ b.Property("FortOpenTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LastLoginTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LastSaveImportTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LastStaminaMultiUpdateTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("LastStaminaSingleUpdateTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Level")
+ .HasColumnType("integer");
+
+ b.Property("MainPartyNo")
+ .HasColumnType("integer");
+
+ b.Property("ManaPoint")
+ .HasColumnType("integer");
+
+ b.Property("MaxDragonQuantity")
+ .HasColumnType("integer");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(10)
+ .HasColumnType("character varying(10)");
+
+ b.Property("QuestSkipPoint")
+ .HasColumnType("integer");
+
+ b.Property("StaminaMulti")
+ .HasColumnType("integer");
+
+ b.Property("StaminaMultiSurplusSecond")
+ .HasColumnType("integer");
+
+ b.Property("StaminaSingle")
+ .HasColumnType("integer");
+
+ b.Property("StaminaSingleSurplusSecond")
+ .HasColumnType("integer");
+
+ b.Property("TutorialFlag")
+ .HasColumnType("integer");
+
+ b.Property("TutorialStatus")
+ .HasColumnType("integer");
+
+ b.Property("ViewerId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("ViewerId"));
+
+ b.HasKey("DeviceAccountId");
+
+ b.HasIndex("DeviceAccountId")
+ .IsUnique();
+
+ b.ToTable("PlayerUserData");
+ });
+
+ modelBuilder.Entity("DragaliaAPI.Database.Entities.DbQuest", b =>
+ {
+ b.Property("DeviceAccountId")
+ .HasColumnType("text");
+
+ b.Property("QuestId")
+ .HasColumnType("integer");
+
+ b.Property("BestClearTime")
+ .HasColumnType("real");
+
+ b.Property("DailyPlayCount")
+ .HasColumnType("integer");
+
+ b.Property("IsAppear")
+ .HasColumnType("boolean");
+
+ b.Property("IsMissionClear1")
+ .HasColumnType("boolean");
+
+ b.Property("IsMissionClear2")
+ .HasColumnType("boolean");
+
+ b.Property