Lots of data and model setup

This commit is contained in:
gamer147
2025-05-18 02:27:17 -04:00
parent 79505e0c1a
commit b2024af852
77 changed files with 81988 additions and 433 deletions

View File

@@ -0,0 +1,215 @@
using System.Globalization;
using CsvHelper;
using CsvHelper.Configuration;
using DCGEngine.Database.Interfaces;
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Models;
namespace SVSim.Database.DataSeeders;
/// <summary>
/// Loads base data aside from cards into the DB. Cards excluded due to how many of them there are.
/// </summary>
public class BaseDataSeeder : IDataSeeder
{
private class ClassEntryMap : ClassMap<ClassEntry>
{
public ClassEntryMap()
{
Map(m => m.Id).Name("id");
Map(m => m.Name).Name("name");
Map(m => m.DefaultLeaderSkin).Ignore();
}
}
private class LeaderSkinEntryMap : ClassMap<LeaderSkinEntry>
{
public LeaderSkinEntryMap()
{
Map(m => m.Id).Name("class_chara_id");
Map(m => m.Name).Name("class_chara_name");
Map(m => m.ClassId).Name("clan");
Map(m => m.Class).Ignore();
Map(m => m.Viewers).Ignore();
Map(m => m.EmoteId).Ignore();
}
}
private class EmblemEntryMap : ClassMap<EmblemEntry>
{
public EmblemEntryMap()
{
Map(m => m.Id).Name("emblem_id");
}
}
private class SleeveEntryMap : ClassMap<SleeveEntry>
{
public SleeveEntryMap()
{
Map(m => m.Id).Name("sleeve_id");
}
}
private class DegreeEntryMap : ClassMap<DegreeEntry>
{
public DegreeEntryMap()
{
Map(m => m.Id).Name("degree_id");
}
}
private class BattlefieldEntryMap : ClassMap<BattlefieldEntry>
{
public BattlefieldEntryMap()
{
Map(m => m.Id).Name("value");
Map(m => m.IsOpen).Name("is_open");
}
}
private class MyPageBackgroundEntryMap : ClassMap<MyPageBackgroundEntry>
{
public MyPageBackgroundEntryMap()
{
Map(m => m.Id).Name("id");
}
}
private class ClassExpEntryMap : ClassMap<ClassExpEntry>
{
public ClassExpEntryMap()
{
Map(m => m.Id).Name("level");
Map(m => m.NecessaryExp).Name("necessary_exp");
}
}
private class RankInfoEntryMap : ClassMap<RankInfoEntry>
{
public RankInfoEntryMap()
{
Map(m => m.Id).Name("rank_id");
Map(m => m.Name).Name("rank_name");
Map(m => m.NecessaryPoint).Name("necessary_point");
Map(m => m.AccumulatePoint).Name("accumulate_point");
Map(m => m.LowerLimitPoint).Name("lower_limit_point");
Map(m => m.BaseAddBp).Name("base_add_bp");
Map(m => m.BaseDropBp).Name("base_drop_bp");
Map(m => m.StreakBonusPt).Name("streak_bonus_pt");
Map(m => m.WinBonus).Name("win_bonus");
Map(m => m.LoseBonus).Name("lose_bonus");
Map(m => m.MaxWinBonus).Name("max_win_bonus");
Map(m => m.MaxLoseBonus).Name("max_lose_bonus");
Map(m => m.IsPromotionWar).Name("is_promotion_war");
Map(m => m.MatchCount).Name("match_count");
Map(m => m.NecessaryWin).Name("necessary_win");
Map(m => m.ResetLose).Name("reset_lose");
Map(m => m.AccumulateMasterPoint).Name("accumulate_master_point");
}
}
public void Seed(ModelBuilder builder)
{
List<ClassEntry> classes = new();
List<LeaderSkinEntry> leaderSkins = new();
List<EmblemEntry> emblems = new();
List<DegreeEntry> degrees = new();
List<SleeveEntry> sleeves = new();
List<BattlefieldEntry> battlefields = new();
List<MyPageBackgroundEntry> myPageBackgrounds = new();
List<ClassExpEntry> classexp = new();
List<RankInfoEntry> rankinfos = new();
using (StreamReader reader = new("data/classes.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<ClassEntryMap>();
IEnumerable<ClassEntry> records = csv.GetRecords<ClassEntry>();
classes.AddRange(records);
}
using (StreamReader reader = new("data/leaderskins.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<LeaderSkinEntryMap>();
IEnumerable<LeaderSkinEntry> records = csv.GetRecords<LeaderSkinEntry>();
leaderSkins.AddRange(records);
leaderSkins.ForEach(skin =>
{
if (skin.ClassId == 0)
{
skin.ClassId = null;
}
});
}
// Load rest of default data
using (StreamReader reader = new("data/emblems.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<EmblemEntryMap>();
IEnumerable<EmblemEntry> records = csv.GetRecords<EmblemEntry>();
emblems.AddRange(records);
}
using (StreamReader reader = new("data/degrees.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<DegreeEntryMap>();
IEnumerable<DegreeEntry> records = csv.GetRecords<DegreeEntry>();
degrees.AddRange(records);
}
using (StreamReader reader = new("data/sleeves.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<SleeveEntryMap>();
IEnumerable<SleeveEntry> records = csv.GetRecords<SleeveEntry>();
sleeves.AddRange(records);
}
using (StreamReader reader = new("data/battlefields.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<BattlefieldEntryMap>();
IEnumerable<BattlefieldEntry> records = csv.GetRecords<BattlefieldEntry>();
battlefields.AddRange(records);
}
using (StreamReader reader = new("data/mypagebackgrounds.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<MyPageBackgroundEntryMap>();
IEnumerable<MyPageBackgroundEntry> records = csv.GetRecords<MyPageBackgroundEntry>();
myPageBackgrounds.AddRange(records);
}
using (StreamReader reader = new("data/ranks.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<RankInfoEntryMap>();
IEnumerable<RankInfoEntry> records = csv.GetRecords<RankInfoEntry>();
rankinfos.AddRange(records);
}
using (StreamReader reader = new("data/classexp.csv"))
{
using CsvReader csv = new(reader, CultureInfo.InvariantCulture);
csv.Context.RegisterClassMap<ClassExpEntryMap>();
IEnumerable<ClassExpEntry> records = csv.GetRecords<ClassExpEntry>();
classexp.AddRange(records);
}
builder.Entity<ClassEntry>().HasData(classes);
builder.Entity<LeaderSkinEntry>().HasData(leaderSkins);
builder.Entity<EmblemEntry>().HasData(emblems);
builder.Entity<SleeveEntry>().HasData(sleeves);
builder.Entity<DegreeEntry>().HasData(degrees);
builder.Entity<BattlefieldEntry>().HasData(battlefields);
builder.Entity<MyPageBackgroundEntry>().HasData(myPageBackgrounds);
builder.Entity<RankInfoEntry>().HasData(rankinfos);
builder.Entity<ClassExpEntry>().HasData(classexp);
}
}

View File

@@ -0,0 +1,28 @@
using DCGEngine.Database.Interfaces;
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Models;
namespace SVSim.Database.DataSeeders;
public class DefaultSettingsSeeder : IDataSeeder
{
public void Seed(ModelBuilder builder)
{
builder.Entity<GameConfiguration>().HasData(new GameConfiguration
{
Id = "default",
DefaultCrystals = 50000,
DefaultRupees = 50000,
DefaultEther = 50000,
MaxFriends = 20,
DefaultEmblemId = 100000000,
DefaultDegreeId = 300003,
DefaultMyPageBackgroundId = 100000000,
DefaultSleeveId = 3000011,
DefaultDegree = null,
DefaultEmblem = null,
DefaultSleeve = null,
DefaultMyPageBackground = null
});
}
}

View File

@@ -0,0 +1,18 @@
namespace SVSim.Database.Enums;
public enum Format
{
Rotation,
Unlimited,
Max,
None = 2,
PreRotation,
Sealed,
MyRotation,
TwoPick = 10,
Hof = 31,
Windfall = 33,
Avatar = 39,
All = 100,
Crossover = 104
}

View File

@@ -1,171 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SVSim.Database;
#nullable disable
namespace SVSim.Database.Migrations
{
[DbContext(typeof(SVSimDbContext))]
[Migration("20240907191709_Initial")]
partial class Initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "8.0.8");
modelBuilder.Entity("DCGEngine.Database.Models.CardEntry", b =>
{
b.Property<long>("Id")
.HasColumnType("INTEGER");
b.Property<int?>("Attack")
.HasColumnType("INTEGER");
b.Property<DateTime?>("DateCreated")
.HasColumnType("TEXT");
b.Property<DateTime?>("DateUpdated")
.HasColumnType("TEXT");
b.Property<int?>("Defense")
.HasColumnType("INTEGER");
b.Property<string>("Discriminator")
.IsRequired()
.HasMaxLength(21)
.HasColumnType("TEXT");
b.Property<string>("InternalName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int?>("PrimaryResourceCost")
.HasColumnType("INTEGER");
b.Property<long?>("ShadowverseDeckEntryId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ShadowverseDeckEntryId");
b.ToTable("CardEntry");
b.HasDiscriminator().HasValue("CardEntry");
b.UseTphMappingStrategy();
});
modelBuilder.Entity("SVSim.Database.Models.ShadowverseDeckEntry", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime?>("DateCreated")
.HasColumnType("TEXT");
b.Property<DateTime?>("DateUpdated")
.HasColumnType("TEXT");
b.Property<string>("InternalName")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("ShadowverseDeckEntry");
});
modelBuilder.Entity("SVSim.Database.Models.SocialAccountConnection", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<ulong>("AccountId")
.HasColumnType("INTEGER");
b.Property<int>("AccountType")
.HasColumnType("INTEGER");
b.Property<DateTime?>("DateCreated")
.HasColumnType("TEXT");
b.Property<DateTime?>("DateUpdated")
.HasColumnType("TEXT");
b.Property<ulong>("ViewerId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ViewerId");
b.ToTable("SocialAccountConnection");
});
modelBuilder.Entity("SVSim.Database.Models.Viewer", b =>
{
b.Property<ulong>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime?>("DateCreated")
.HasColumnType("TEXT");
b.Property<DateTime?>("DateUpdated")
.HasColumnType("TEXT");
b.Property<string>("DisplayName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<ulong>("ShortUdid")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Viewer");
});
modelBuilder.Entity("SVSim.Database.Models.ShadowverseCardEntry", b =>
{
b.HasBaseType("DCGEngine.Database.Models.CardEntry");
b.HasDiscriminator().HasValue("ShadowverseCardEntry");
});
modelBuilder.Entity("DCGEngine.Database.Models.CardEntry", b =>
{
b.HasOne("SVSim.Database.Models.ShadowverseDeckEntry", null)
.WithMany("Cards")
.HasForeignKey("ShadowverseDeckEntryId");
});
modelBuilder.Entity("SVSim.Database.Models.SocialAccountConnection", b =>
{
b.HasOne("SVSim.Database.Models.Viewer", "Viewer")
.WithMany()
.HasForeignKey("ViewerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Viewer");
});
modelBuilder.Entity("SVSim.Database.Models.ShadowverseDeckEntry", b =>
{
b.Navigation("Cards");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -1,118 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace SVSim.Database.Migrations
{
/// <inheritdoc />
public partial class Initial : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ShadowverseDeckEntry",
columns: table => new
{
Id = table.Column<long>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DateCreated = table.Column<DateTime>(type: "TEXT", nullable: true),
DateUpdated = table.Column<DateTime>(type: "TEXT", nullable: true),
InternalName = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShadowverseDeckEntry", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Viewer",
columns: table => new
{
Id = table.Column<ulong>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
DisplayName = table.Column<string>(type: "TEXT", nullable: false),
ShortUdid = table.Column<ulong>(type: "INTEGER", nullable: false),
DateCreated = table.Column<DateTime>(type: "TEXT", nullable: true),
DateUpdated = table.Column<DateTime>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Viewer", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CardEntry",
columns: table => new
{
Id = table.Column<long>(type: "INTEGER", nullable: false),
InternalName = table.Column<string>(type: "TEXT", nullable: false),
Attack = table.Column<int>(type: "INTEGER", nullable: true),
Defense = table.Column<int>(type: "INTEGER", nullable: true),
PrimaryResourceCost = table.Column<int>(type: "INTEGER", nullable: true),
Discriminator = table.Column<string>(type: "TEXT", maxLength: 21, nullable: false),
ShadowverseDeckEntryId = table.Column<long>(type: "INTEGER", nullable: true),
DateCreated = table.Column<DateTime>(type: "TEXT", nullable: true),
DateUpdated = table.Column<DateTime>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_CardEntry", x => x.Id);
table.ForeignKey(
name: "FK_CardEntry_ShadowverseDeckEntry_ShadowverseDeckEntryId",
column: x => x.ShadowverseDeckEntryId,
principalTable: "ShadowverseDeckEntry",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "SocialAccountConnection",
columns: table => new
{
Id = table.Column<Guid>(type: "TEXT", nullable: false),
AccountType = table.Column<int>(type: "INTEGER", nullable: false),
AccountId = table.Column<ulong>(type: "INTEGER", nullable: false),
ViewerId = table.Column<ulong>(type: "INTEGER", nullable: false),
DateCreated = table.Column<DateTime>(type: "TEXT", nullable: true),
DateUpdated = table.Column<DateTime>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_SocialAccountConnection", x => x.Id);
table.ForeignKey(
name: "FK_SocialAccountConnection_Viewer_ViewerId",
column: x => x.ViewerId,
principalTable: "Viewer",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_CardEntry_ShadowverseDeckEntryId",
table: "CardEntry",
column: "ShadowverseDeckEntryId");
migrationBuilder.CreateIndex(
name: "IX_SocialAccountConnection_ViewerId",
table: "SocialAccountConnection",
column: "ViewerId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "CardEntry");
migrationBuilder.DropTable(
name: "SocialAccountConnection");
migrationBuilder.DropTable(
name: "ShadowverseDeckEntry");
migrationBuilder.DropTable(
name: "Viewer");
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class BattlefieldEntry : BaseEntity<int>
{
public string Name { get; set; } = string.Empty;
public bool IsOpen { get; set; }
}

View File

@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
[Owned]
public class CollectionInfo
public class CardCollectionInfo
{
public int CraftCost { get; set; }
public int DustReward { get; set; }

View File

@@ -9,4 +9,14 @@ public class ClassEntry : BaseEntity<int>
/// The name of the class.
/// </summary>
public string Name { get; set; } = string.Empty;
#region Navigation Properties
public List<LeaderSkinEntry> LeaderSkins { get; set; } = new List<LeaderSkinEntry>();
[NotMapped]
public LeaderSkinEntry? DefaultLeaderSkin => LeaderSkins.FirstOrDefault(skin => skin.Id == Id);
#endregion
}

View File

@@ -0,0 +1,8 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class ClassExpEntry : BaseEntity<int>
{
public int NecessaryExp { get; set; }
}

View File

@@ -4,5 +4,9 @@ namespace SVSim.Database.Models;
public class DegreeEntry : BaseEntity<int>
{
#region Navigation Properties
public List<Viewer> Viewers { get; set; } = new List<Viewer>();
#endregion
}

View File

@@ -2,7 +2,11 @@ using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class EmblemEntry : BaseEntity<long>
public class EmblemEntry : BaseEntity<int>
{
#region Navigation Properties
public List<Viewer> Viewers { get; set; } = new List<Viewer>();
#endregion
}

View File

@@ -0,0 +1,36 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class GameConfiguration : BaseEntity<string>
{
public ulong DefaultCrystals { get; set; }
public ulong DefaultRupees { get; set; }
public ulong DefaultEther { get; set; }
public int MaxFriends { get; set; }
#region Foreign Keys
public int DefaultDegreeId { get; set; }
public int DefaultEmblemId { get; set; }
public int DefaultMyPageBackgroundId { get; set; }
public int DefaultSleeveId { get; set; }
#endregion
#region Navigation Properties
public DegreeEntry DefaultDegree { get; set; } = new DegreeEntry();
public EmblemEntry DefaultEmblem { get; set; } = new EmblemEntry();
public MyPageBackgroundEntry DefaultMyPageBackground { get; set; } = new MyPageBackgroundEntry();
public SleeveEntry DefaultSleeve { get; set; } = new SleeveEntry();
#endregion
}

View File

@@ -2,7 +2,7 @@ using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class FormatEntry : BaseEntity<int>
public class ItemEntry : BaseEntity<int>
{
public string Name { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,26 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class LeaderSkinEntry : BaseEntity<int>
{
// Name of the skin
public string Name { get; set; } = string.Empty;
// ID of the emote associated with the skin
public int EmoteId { get; set; }
#region Foreign Keys
public int? ClassId { get; set; }
#endregion
#region Navigation Properties
public ClassEntry? Class { get; set; }
public List<Viewer> Viewers { get; set; } = new List<Viewer>();
#endregion
}

View File

@@ -0,0 +1,12 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class MyPageBackgroundEntry : BaseEntity<int>
{
#region Navigation Properties
public List<Viewer> Viewers { get; set; } = new List<Viewer>();
#endregion
}

View File

@@ -0,0 +1,15 @@
using DCGEngine.Database.Models;
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
/// <summary>
/// Represents viewer ownership of a <see cref="ShadowverseCardEntry"/>.
/// </summary>
[Owned]
public class OwnedCardEntry
{
public CardEntry Card { get; set; } = new ShadowverseCardEntry();
public int Count { get; set; }
public bool IsProtected { get; set; }
}

View File

@@ -0,0 +1,17 @@
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
[Owned]
public class OwnedItemEntry
{
public int Count { get; set; }
#region Navigation Properties
public ItemEntry Item { get; set; } = new ItemEntry();
public Viewer Viewer { get; set; } = new Viewer();
#endregion
}

View File

@@ -0,0 +1,23 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class RankInfoEntry : BaseEntity<int>
{
public string Name { get; set; } = string.Empty;
public int NecessaryPoint { get; set; }
public int AccumulatePoint { get; set; }
public int LowerLimitPoint { get; set; }
public int BaseAddBp { get; set; }
public int BaseDropBp { get; set; }
public int StreakBonusPt { get; set; }
public double WinBonus { get; set; }
public double LoseBonus { get; set; }
public int MaxWinBonus { get; set; }
public int MaxLoseBonus { get; set; }
public int IsPromotionWar { get; set; }
public int MatchCount { get; set; }
public int NecessaryWin { get; set; }
public int ResetLose { get; set; }
public int AccumulateMasterPoint { get; set; }
}

View File

@@ -17,7 +17,7 @@ public class ShadowverseCardEntry : CardEntry
/// <summary>
/// Info about this card in the collection, if it can be collected.
/// </summary>
public CollectionInfo? CollectionInfo { get; set; }
public CardCollectionInfo? CollectionInfo { get; set; }
#endregion
@@ -28,10 +28,5 @@ public class ShadowverseCardEntry : CardEntry
/// </summary>
public ClassEntry? Class { get; set; }
/// <summary>
/// The set this card belongs to.
/// </summary>
public CardSetEntry CardSet { get; set; } = new ShadowverseCardSetEntry();
#endregion
}

View File

@@ -5,4 +5,6 @@ namespace SVSim.Database.Models;
public class ShadowverseCardSetEntry : CardSetEntry
{
public bool IsInRotation { get; set; }
public bool IsBasic { get; set; }
}

View File

@@ -1,8 +1,22 @@
using DCGEngine.Database.Models;
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Enums;
namespace SVSim.Database.Models;
public class ShadowverseDeckEntry : DeckEntry
{
public int Number { get; set; }
public Format Format { get; set; }
public bool RandomLeaderSkin { get; set; }
#region Navigation Properties
public ClassEntry Class { get; set; } = new ClassEntry();
public SleeveEntry Sleeve { get; set; } = new SleeveEntry();
public LeaderSkinEntry LeaderSkin { get; set; } = new LeaderSkinEntry();
#endregion
}

View File

@@ -0,0 +1,13 @@
using DCGEngine.Database.Models;
namespace SVSim.Database.Models;
public class SleeveEntry : BaseEntity<int>
{
#region Navigation Properties
public List<Viewer> Viewers = new List<Viewer>();
#endregion
}

View File

@@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Models;
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Enums;
namespace SVSim.Database.Models;
@@ -7,11 +8,9 @@ namespace SVSim.Database.Models;
/// <summary>
/// A connection between a social account (ie facebook) and a viewer.
/// </summary>
public class SocialAccountConnection : BaseEntity<Guid>
[Owned]
public class SocialAccountConnection
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override Guid Id { get; set; }
/// <summary>
/// The type of the social account.
/// </summary>
@@ -21,9 +20,9 @@ public class SocialAccountConnection : BaseEntity<Guid>
/// The identifier of the social account.
/// </summary>
public ulong AccountId { get; set; }
/// <summary>
/// The viewer connected.
/// </summary>
public Viewer Viewer { get; set; }
public Viewer Viewer { get; set; } = new Viewer();
}

View File

@@ -1,15 +1,17 @@
using System.ComponentModel.DataAnnotations.Schema;
using DCGEngine.Database.Models;
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
/// <summary>
/// A user within the game system.
/// </summary>
public class Viewer : BaseEntity<ulong>
[Index(nameof(ShortUdid))]
public class Viewer : BaseEntity<long>
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override ulong Id { get; set; }
public override long Id { get; set; }
/// <summary>
/// This user's name displayed in game.
@@ -19,7 +21,7 @@ public class Viewer : BaseEntity<ulong>
/// <summary>
/// This user's short identifier.
/// </summary>
public ulong ShortUdid { get; set; }
public long ShortUdid { get; set; }
public DateTime LastLogin { get; set; }
@@ -31,6 +33,28 @@ public class Viewer : BaseEntity<ulong>
public ViewerCurrency Currency { get; set; } = new ViewerCurrency();
public List<ViewerClassData> Classes { get; set; } = new List<ViewerClassData>();
#endregion
#region Collection
public List<ShadowverseDeckEntry> Decks { get; set; } = new List<ShadowverseDeckEntry>();
public List<OwnedCardEntry> Cards { get; set; } = new List<OwnedCardEntry>();
public List<LeaderSkinEntry> LeaderSkins { get; set; } = new List<LeaderSkinEntry>();
public List<DegreeEntry> Degrees { get; set; } = new List<DegreeEntry>();
public List<EmblemEntry> Emblems { get; set; } = new List<EmblemEntry>();
public List<OwnedItemEntry> Items { get; set; } = new List<OwnedItemEntry>();
public List<SleeveEntry> Sleeves { get; set; } = new List<SleeveEntry>();
public List<MyPageBackgroundEntry> MyPageBackgrounds { get; set; } = new List<MyPageBackgroundEntry>();
#endregion
#region Navigation Properties

View File

@@ -0,0 +1,20 @@
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Models;
[Owned]
public class ViewerClassData
{
public int Level { get; set; }
public int Exp { get; set; }
#region Navigation Properties
public ClassEntry Class { get; set; } = new ClassEntry();
public Viewer Viewer { get; set; } = new Viewer();
public LeaderSkinEntry LeaderSkin { get; set; } = new LeaderSkinEntry();
#endregion
}

View File

@@ -11,7 +11,6 @@ public class ViewerCurrency
public ulong SteamCrystals { get; set; }
public ulong DmmCrystals { get; set; }
public ulong FreeCrystals { get; set; }
public ulong TotalCrystals { get; set; }
public ulong LifeTotalCrystals { get; set; }
public ulong RedEther { get; set; }
public ulong Rupees { get; set; }

View File

@@ -0,0 +1,15 @@
using Microsoft.EntityFrameworkCore;
namespace SVSim.Database.Repositories;
public abstract class BaseRepository<T> where T : class
{
protected readonly SVSimDbContext DbContext;
protected readonly DbSet<T> DbSet;
public BaseRepository(SVSimDbContext dbContext)
{
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
}

View File

@@ -0,0 +1,30 @@
using DCGEngine.Database.Models;
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Models;
namespace SVSim.Database.Repositories.Card;
public class CardRepository : BaseRepository<ShadowverseCardEntry>, ICardRepository
{
public CardRepository(SVSimDbContext dbContext) : base(dbContext)
{
}
public async Task<List<ShadowverseCardEntry>> GetAll(bool onlyCollectible)
{
var cards = await DbSet.AsNoTracking().Where(card => !onlyCollectible || card.CollectionInfo != null).ToListAsync();
return cards;
}
public async Task<List<ShadowverseCardEntry>> GetAllBasic()
{
return await DbContext.Set<ShadowverseCardSetEntry>().Where(set => set.IsBasic).SelectMany(set => set.Cards)
.Cast<ShadowverseCardEntry>().ToListAsync();
}
public async Task<List<ShadowverseCardSetEntry>> GetCardSets(bool onlyInRotation)
{
return await DbContext.Set<ShadowverseCardSetEntry>().AsNoTracking()
.Where(set => !onlyInRotation || set.IsInRotation).ToListAsync();
}
}

View File

@@ -0,0 +1,10 @@
using SVSim.Database.Models;
namespace SVSim.Database.Repositories.Card;
public interface ICardRepository
{
Task<List<ShadowverseCardEntry>> GetAll(bool onlyCollectible);
Task<List<ShadowverseCardSetEntry>> GetCardSets(bool onlyInRotation);
Task<List<ShadowverseCardEntry>> GetAllBasic();
}

View File

@@ -0,0 +1,19 @@
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Models;
namespace SVSim.Database.Repositories.Collectibles;
public class CollectionRepository : ICollectionRepository
{
private readonly SVSimDbContext _dbContext;
public CollectionRepository(SVSimDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<List<LeaderSkinEntry>> GetLeaderSkins()
{
return await _dbContext.Set<LeaderSkinEntry>().AsNoTracking().Include(skin => skin.Class).ToListAsync();
}
}

View File

@@ -0,0 +1,8 @@
using SVSim.Database.Models;
namespace SVSim.Database.Repositories.Collectibles;
public interface ICollectionRepository
{
Task<List<LeaderSkinEntry>> GetLeaderSkins();
}

View File

@@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Models;
namespace SVSim.Database.Repositories.Globals;
public class GlobalsRepository : IGlobalsRepository
{
private readonly SVSimDbContext _dbContext;
public GlobalsRepository(SVSimDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<List<ClassExpEntry>> GetClassExpCurve()
{
return await _dbContext.Set<ClassExpEntry>().ToListAsync();
}
public async Task<List<BattlefieldEntry>> GetBattlefields(bool onlyOpen)
{
return await _dbContext.Set<BattlefieldEntry>().Where(bf => !onlyOpen || bf.IsOpen).ToListAsync();
}
public async Task<GameConfiguration> GetGameConfiguration(string key)
{
return await _dbContext.Set<GameConfiguration>().Include(gc => gc.DefaultMyPageBackground)
.Include(gc => gc.DefaultEmblem).Include(gc => gc.DefaultDegree).Include(gc => gc.DefaultSleeve).FirstOrDefaultAsync(gc => gc.Id == key) ??
new GameConfiguration();
}
public async Task<List<RankInfoEntry>> GetRankInfo()
{
return await _dbContext.Set<RankInfoEntry>().ToListAsync();
}
}

View File

@@ -0,0 +1,11 @@
using SVSim.Database.Models;
namespace SVSim.Database.Repositories.Globals;
public interface IGlobalsRepository
{
Task<List<ClassExpEntry>> GetClassExpCurve();
Task<List<BattlefieldEntry>> GetBattlefields(bool onlyOpen);
Task<GameConfiguration> GetGameConfiguration(string key);
Task<List<RankInfoEntry>> GetRankInfo();
}

View File

@@ -5,6 +5,9 @@ namespace SVSim.Database.Repositories.Viewer;
public interface IViewerRepository
{
Task<Models.Viewer?> GetViewerBySocialConnection(SocialAccountType accountType, ulong socialId);
Task<Models.Viewer?> GetViewerWithSocials(ulong id);
Task<Models.Viewer?> GetViewerByShortUdid(ulong shortUdid);
Task<Models.Viewer?> GetViewerWithSocials(long id);
Task<Models.Viewer?> GetViewerByShortUdid(long shortUdid);
Task<Models.Viewer> RegisterViewer(string displayName, SocialAccountType socialType,
ulong socialAccountIdentifier, ulong? shortUdid = null);
}

View File

@@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore;
using SVSim.Database.Enums;
using SVSim.Database.Models;
using SVSim.Database.Repositories.Card;
using SVSim.Database.Repositories.Globals;
namespace SVSim.Database.Repositories.Viewer;
@@ -8,6 +10,8 @@ public class ViewerRepository : IViewerRepository
{
protected readonly SVSimDbContext _dbContext;
private const int MaxFriends = 20;
public ViewerRepository(SVSimDbContext dbContext)
{
_dbContext = dbContext;
@@ -22,15 +26,58 @@ public class ViewerRepository : IViewerRepository
?.Viewer;
}
public async Task<Models.Viewer?> GetViewerWithSocials(ulong id)
public async Task<Models.Viewer?> GetViewerWithSocials(long id)
{
return await _dbContext.Set<Models.Viewer>().AsNoTracking().Include(viewer => viewer.SocialAccountConnections)
.FirstOrDefaultAsync(viewer => viewer.Id == id);
}
public async Task<Models.Viewer?> GetViewerByShortUdid(ulong shortUdid)
public async Task<Models.Viewer?> GetViewerByShortUdid(long shortUdid)
{
return await _dbContext.Set<Models.Viewer>().AsNoTracking().Include(viewer => viewer.MissionData)
.Include(viewer => viewer.Info).FirstOrDefaultAsync(viewer => viewer.ShortUdid == shortUdid);
}
public async Task<Models.Viewer> RegisterViewer(string displayName, SocialAccountType socialType,
ulong socialAccountIdentifier, ulong? shortUdid = null)
{
Models.Viewer viewer = new Models.Viewer
{
DisplayName = displayName
};
GameConfiguration gameConfig = await new GlobalsRepository(_dbContext).GetGameConfiguration("default");
viewer.SocialAccountConnections.Add(new SocialAccountConnection
{
AccountId = socialAccountIdentifier,
AccountType = socialType
});
viewer.Info.MaxFriends = gameConfig.MaxFriends;
viewer.Info.CountryCode = "KOR";
viewer.Info.BirthDate = DateTime.UtcNow;
viewer.Currency.Crystals = gameConfig.DefaultCrystals;
viewer.Currency.Rupees = gameConfig.DefaultRupees;
viewer.Currency.RedEther = gameConfig.DefaultEther;
viewer.MissionData.TutorialState = 100; // finishes tutorial for now
List<ClassEntry> classes = await _dbContext.Set<ClassEntry>().ToListAsync();
viewer.Classes = classes.Select(ce => new ViewerClassData
{
Class = ce,
Exp = 0,
Level = 0,
LeaderSkin = ce.DefaultLeaderSkin
}).ToList();
viewer.Sleeves.Add(gameConfig.DefaultSleeve);
viewer.Degrees.Add(gameConfig.DefaultDegree);
viewer.Emblems.Add(gameConfig.DefaultEmblem);
viewer.MyPageBackgrounds.Add(gameConfig.DefaultMyPageBackground);
viewer.LeaderSkins.AddRange(viewer.Classes.Select(vcd => vcd.LeaderSkin));
_dbContext.Set<Models.Viewer>().Add(viewer);
await _dbContext.SaveChangesAsync();
return viewer;
}
}

View File

@@ -10,4 +10,12 @@
<ProjectReference Include="..\DCGEngine.Database\DCGEngine.Database.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Data\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="33.0.1" />
</ItemGroup>
</Project>

View File

@@ -3,6 +3,7 @@ using DCGEngine.Database.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SVSim.Database.Models;
namespace SVSim.Database;
@@ -11,4 +12,19 @@ public class SVSimDbContext : DCGEDbContext
public SVSimDbContext(IOptions<DCGEDatabaseConfiguration> configuration, ILogger<DCGEDbContext> logger, DbContextOptions options) : base(configuration, logger, options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// For whatever reason it cannot figure out this relationship on it's own
modelBuilder.Entity<SleeveEntry>()
.HasMany<Viewer>(se => se.Viewers)
.WithMany(v => v.Sleeves);
modelBuilder.HasSequence<long>("ShortUdidSequence").StartsAt(400000000);
modelBuilder.Entity<Viewer>()
.Property(v => v.ShortUdid)
.UseSequence("ShortUdidSequence");
}
}