diff --git a/Directory.Packages.props b/Directory.Packages.props index f1da168..8ae774b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,8 +5,6 @@ - - diff --git a/src/Open5ETools.Core/Common/Constants.cs b/src/Open5ETools.Core/Common/Constants.cs index 8be994c..25036fd 100644 --- a/src/Open5ETools.Core/Common/Constants.cs +++ b/src/Open5ETools.Core/Common/Constants.cs @@ -21,7 +21,8 @@ public static class Constants public const string MonsterError = "Monster: No suitable monsters with this settings"; // door - public static readonly string[] DoorTypes = [ + public static readonly string[] DoorTypes = + [ "Crystal", "Wooden", "Stone", @@ -30,7 +31,9 @@ public static class Constants "Mithral", "Adamantine" ]; - public static readonly int[] DoorAc = [ + + public static readonly int[] DoorAc = + [ 13, 15, 17, @@ -39,7 +42,9 @@ public static class Constants 21, 23 ]; - public static readonly int[] DoorHp = [ + + public static readonly int[] DoorHp = + [ 10, 10, 15, @@ -48,7 +53,9 @@ public static class Constants 18, 27 ]; - public static readonly int[] LockDifficulty = [ + + public static readonly int[] LockDifficulty = + [ 5, 10, 15, @@ -57,8 +64,10 @@ public static class Constants 25, 30 ]; + // treasure - public static readonly int[] TreasureGp = [ + public static readonly int[] TreasureGp = + [ 0, 300, 600, @@ -81,7 +90,9 @@ public static class Constants 61000, 80000 ]; - public static readonly int[] ItemCount = [ + + public static readonly int[] ItemCount = + [ 0, 4, 4, @@ -104,25 +115,32 @@ public static class Constants 15, 15 ]; + // trap - public static readonly int[] TrapSave = [ + public static readonly int[] TrapSave = + [ 10, 12, 16, 21 ]; - public static readonly int[] TrapAttackBonus = [ + + public static readonly int[] TrapAttackBonus = + [ 3, 6, 9, 13 ]; - public static readonly int[,] TrapDmgSeverity = { - {1, 2, 4}, - {2, 4, 10}, - {4, 10, 18}, - {10, 18, 24} + + public static readonly int[,] TrapDmgSeverity = + { + { 1, 2, 4 }, + { 2, 4, 10 }, + { 4, 10, 18 }, + { 10, 18, 24 } }; + public static readonly ImmutableArray SimpleTraps = [ new Trap("Collapsing Roof", Save.Dexterity, 10, 15, DisableCheck.Dexterity, false, DamageType.Bludgeoning, ""), @@ -138,17 +156,21 @@ public static class Constants public static readonly ImmutableArray DoorTraps = [ new Trap("Fire trap", Save.Dexterity, 10, 15, DisableCheck.Intelligence, false, DamageType.Fire, ""), - new Trap("Lock Covered in Dragon Bile", Save.Constitution, 10, 15, DisableCheck.Intelligence, false, DamageType.Poison, ""), + new Trap("Lock Covered in Dragon Bile", Save.Constitution, 10, 15, DisableCheck.Intelligence, false, + DamageType.Poison, ""), new Trap("Hail of Needles", Save.Dexterity, 15, 13, DisableCheck.Dexterity, false, DamageType.Piercing, ""), - new Trap("Stone Blocks from Ceiling", Save.Dexterity, 15, 15, DisableCheck.Intelligence, false, DamageType.Bludgeoning, ""), - new Trap("Doorknob Smeared with Contact Poison", Save.Constitution, 15, 10, DisableCheck.Intelligence, false, DamageType.Poison, ""), + new Trap("Stone Blocks from Ceiling", Save.Dexterity, 15, 15, DisableCheck.Intelligence, false, + DamageType.Bludgeoning, ""), + new Trap("Doorknob Smeared with Contact Poison", Save.Constitution, 15, 10, DisableCheck.Intelligence, false, + DamageType.Poison, ""), new Trap("Poison Darts", Save.Constitution, 15, 15, DisableCheck.Intelligence, true, DamageType.Poison, ""), new Trap("Poison Needle", Save.Constitution, 15, 15, DisableCheck.Dexterity, false, DamageType.Poison, ""), new Trap("Energy Drain", Save.Constitution, 15, 15, DisableCheck.DispelMagic, false, DamageType.Necrotic, "") ]; // encounter - public static readonly int[] ChallengeRatingXp = [ + public static readonly int[] ChallengeRatingXp = + [ 10, 25, 50, @@ -184,15 +206,19 @@ public static class Constants 135000, 155000 ]; - public static readonly double[,] Multipliers = { - {1, 1}, - {2, 1.5}, - {3, 2}, - {7, 2.5}, - {11, 3}, - {15, 4} + + public static readonly double[,] Multipliers = + { + { 1, 1 }, + { 2, 1.5 }, + { 3, 2 }, + { 7, 2.5 }, + { 11, 3 }, + { 15, 4 } }; + public static readonly int[] MultipliersIndexes = [.. Enumerable.Range(0, Multipliers.GetLength(0))]; + public static readonly ImmutableArray ChallengeRating = [ "0", @@ -231,27 +257,28 @@ public static class Constants "30" ]; - public static readonly int[,] Thresholds = { - {0, 0, 0, 0}, - {25, 50, 75, 100}, - {50, 100, 150, 200}, - {75, 150, 225, 400}, - {125, 250, 375, 500}, - {250, 500, 750, 1100}, - {300, 600, 900, 1400}, - {350, 750, 1100, 1700}, - {450, 900, 1400, 2100}, - {550, 1100, 1600, 2400}, - {600, 1200, 1900, 2800}, - {800, 1600, 2400, 3600}, - {1000, 2000, 3000, 4500}, - {1100, 2200, 3400, 5100}, - {1250, 2500, 3800, 5700}, - {1400, 2800, 4300, 6400}, - {1600, 3200, 4800, 7200}, - {2000, 3900, 5900, 8800}, - {2100, 4200, 6300, 9500}, - {2400, 4900, 7300, 10900}, - {2800, 5700, 8500, 12700} + public static readonly int[,] Thresholds = + { + { 0, 0, 0, 0 }, + { 25, 50, 75, 100 }, + { 50, 100, 150, 200 }, + { 75, 150, 225, 400 }, + { 125, 250, 375, 500 }, + { 250, 500, 750, 1100 }, + { 300, 600, 900, 1400 }, + { 350, 750, 1100, 1700 }, + { 450, 900, 1400, 2100 }, + { 550, 1100, 1600, 2400 }, + { 600, 1200, 1900, 2800 }, + { 800, 1600, 2400, 3600 }, + { 1000, 2000, 3000, 4500 }, + { 1100, 2200, 3400, 5100 }, + { 1250, 2500, 3800, 5700 }, + { 1400, 2800, 4300, 6400 }, + { 1600, 3200, 4800, 7200 }, + { 2000, 3900, 5900, 8800 }, + { 2100, 4200, 6300, 9500 }, + { 2400, 4900, 7300, 10900 }, + { 2800, 5700, 8500, 12700 } }; } \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Helpers/JsonHelper.cs b/src/Open5ETools.Core/Common/Helpers/JsonHelper.cs index 9ad42a9..4cf8879 100644 --- a/src/Open5ETools.Core/Common/Helpers/JsonHelper.cs +++ b/src/Open5ETools.Core/Common/Helpers/JsonHelper.cs @@ -13,10 +13,10 @@ public static class JsonHelper PropertyNameCaseInsensitive = true }; - public static IList DeserializeJson(string fileName) + public static List DeserializeJson(string fileName) { var json = File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "/Data/" + fileName) ?? throw new FileNotFoundException(fileName); - return JsonSerializer.Deserialize>(json, Options) ?? []; + return JsonSerializer.Deserialize>(json, Options) ?? []; } } \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Helpers/SelectListHelper.cs b/src/Open5ETools.Core/Common/Helpers/SelectListHelper.cs index dfc9d68..57e3b00 100644 --- a/src/Open5ETools.Core/Common/Helpers/SelectListHelper.cs +++ b/src/Open5ETools.Core/Common/Helpers/SelectListHelper.cs @@ -4,7 +4,7 @@ namespace Open5ETools.Core.Common.Helpers; public static class SelectListHelper { - public static List GetBool() + public static SelectListItem[] GetBool() { return [ @@ -13,14 +13,15 @@ public static List GetBool() ]; } - public static List GenerateIntSelectList(int from, int to) + public static SelectListItem[] GenerateIntSelectList(int from, int to) { - var list = new List(); - for (var i = from; i <= to; i++) + var ints = Enumerable.Range(from, to - from + 1).ToArray(); + var selectList = new SelectListItem[ints.Length]; + for (var i = 0; i <= ints.Length - 1; i++) { - list.Add(new SelectListItem { Text = i.ToString(), Value = i.ToString() }); + selectList[i] = new SelectListItem { Text = ints[i].ToString(), Value = ints[i].ToString() }; } - return list; + return selectList; } } \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Interfaces/Services/EG/IEncounterService.cs b/src/Open5ETools.Core/Common/Interfaces/Services/EG/IEncounterService.cs index 3a13737..6d676fa 100644 --- a/src/Open5ETools.Core/Common/Interfaces/Services/EG/IEncounterService.cs +++ b/src/Open5ETools.Core/Common/Interfaces/Services/EG/IEncounterService.cs @@ -6,5 +6,5 @@ public interface IEncounterService { Task GetMonsterByIdAsync(int id); Task GenerateAsync(EncounterOption option); - Task>> GetEnumListAsync() where T : struct; + Task[]> GetEnumListAsync() where T : struct; } \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Interfaces/Services/IAuthService.cs b/src/Open5ETools.Core/Common/Interfaces/Services/IAuthService.cs index e6b9851..78d4854 100644 --- a/src/Open5ETools.Core/Common/Interfaces/Services/IAuthService.cs +++ b/src/Open5ETools.Core/Common/Interfaces/Services/IAuthService.cs @@ -4,5 +4,5 @@ namespace Open5ETools.Core.Common.Interfaces.Services; public interface IAuthService { - Task LoginAsync(UserModel model, CancellationToken cancellationToken = default); + Task LoginAsync(string userName, string password, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Interfaces/Services/SM/ISpellService.cs b/src/Open5ETools.Core/Common/Interfaces/Services/SM/ISpellService.cs index fa74a30..c3c7220 100644 --- a/src/Open5ETools.Core/Common/Interfaces/Services/SM/ISpellService.cs +++ b/src/Open5ETools.Core/Common/Interfaces/Services/SM/ISpellService.cs @@ -5,5 +5,5 @@ namespace Open5ETools.Core.Common.Interfaces.Services.SM; public interface ISpellService { Task GetAsync(int id, CancellationToken cancellationToken = default); - Task> ListAsync(string? search = null, CancellationToken cancellationToken = default); + Task ListAsync(string? search = null, CancellationToken cancellationToken = default); } diff --git a/src/Open5ETools.Core/Common/Mappers/DungeonMapper.cs b/src/Open5ETools.Core/Common/Mappers/DungeonMapper.cs new file mode 100644 index 0000000..31b6a09 --- /dev/null +++ b/src/Open5ETools.Core/Common/Mappers/DungeonMapper.cs @@ -0,0 +1,113 @@ +using Open5ETools.Core.Common.Models.DM.Services; +using Open5ETools.Core.Domain.DM; + +namespace Open5ETools.Core.Common.Mappers; + +public static class DungeonMapper +{ + public static DungeonOption ToEntity(this DungeonOptionModel dungeonOption) + { + return new DungeonOption + { + DungeonName = dungeonOption.DungeonName, + DungeonSize = dungeonOption.DungeonSize, + DungeonDifficulty = dungeonOption.DungeonDifficulty, + PartyLevel = dungeonOption.PartyLevel, + PartySize = dungeonOption.PartySize, + TreasureValue = dungeonOption.TreasureValue, + ItemsRarity = dungeonOption.ItemsRarity, + RoomDensity = dungeonOption.RoomDensity, + RoomSize = dungeonOption.RoomSize, + MonsterType = dungeonOption.MonsterType, + TrapPercent = dungeonOption.TrapPercent, + DeadEnd = dungeonOption.DeadEnd, + Corridor = dungeonOption.Corridor, + RoamingPercent = dungeonOption.RoamingPercent, + UserId = dungeonOption.UserId, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty, + Dungeons = + [ + .. dungeonOption.Dungeons.Select(d => d.ToEntity()) + ] + }; + } + + public static DungeonOptionModel ToModel(this DungeonOption dungeonOption) + { + return new DungeonOptionModel + ( + dungeonOption.DungeonName, + dungeonOption.UserId, + dungeonOption.DungeonSize, + dungeonOption.DungeonDifficulty, + dungeonOption.PartyLevel, + dungeonOption.PartySize, + dungeonOption.TreasureValue, + dungeonOption.ItemsRarity, + dungeonOption.RoomDensity, + dungeonOption.RoomSize, + dungeonOption.MonsterType, + dungeonOption.TrapPercent, + dungeonOption.DeadEnd, + dungeonOption.Corridor, + dungeonOption.RoamingPercent, + [.. dungeonOption.Dungeons.Select(d => d.ToModel())], + dungeonOption.Id, + dungeonOption.Timestamp, + dungeonOption.CreatedBy, + dungeonOption.Created, + dungeonOption.LastModifiedBy, + dungeonOption.LastModified + ); + } + + public static void Map(Dungeon dungeon, DungeonModel model) + { + dungeon.DungeonTiles = model.DungeonTiles; + dungeon.DungeonTiles = model.DungeonTiles; + dungeon.RoomDescription = model.RoomDescription; + dungeon.TrapDescription = model.TrapDescription; + dungeon.RoamingMonsterDescription = model.RoamingMonsterDescription; + dungeon.Level = model.Level; + dungeon.DungeonOptionId = model.DungeonOptionId; + } + + public static Dungeon ToEntity(this DungeonModel model) + { + return new Dungeon + { + DungeonTiles = model.DungeonTiles, + RoomDescription = model.RoomDescription, + TrapDescription = model.TrapDescription, + RoamingMonsterDescription = model.RoamingMonsterDescription, + Level = model.Level, + DungeonOptionId = model.DungeonOptionId, + Id = model.Id, + Timestamp = model.Timestamp, + CreatedBy = model.CreatedBy, + Created = model.Created, + LastModifiedBy = model.LastModifiedBy, + LastModified = model.LastModified + }; + } + + public static DungeonModel ToModel(this Dungeon model) + { + return new DungeonModel + ( + model.DungeonTiles, + model.RoomDescription, + model.TrapDescription, + model.RoamingMonsterDescription, + model.DungeonOptionId, + model.Level, + model.Id, + model.Timestamp, + model.CreatedBy, + model.Created, + model.LastModifiedBy, + model.LastModified + ); + } +} \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Mappers/EncounterMapper.cs b/src/Open5ETools.Core/Common/Mappers/EncounterMapper.cs new file mode 100644 index 0000000..6de8b1d --- /dev/null +++ b/src/Open5ETools.Core/Common/Mappers/EncounterMapper.cs @@ -0,0 +1,120 @@ +using Open5ETools.Core.Common.Enums.EG; +using Open5ETools.Core.Common.Extensions; +using Open5ETools.Core.Common.Models.EG; +using Open5ETools.Core.Domain.EG; + +namespace Open5ETools.Core.Common.Mappers; + +public static class EncounterMapper +{ + extension(Monster monster) + { + public MonsterModel ToModel(Difficulty difficulty, int allXp, int count) + { + return new MonsterModel( + new JsonMonsterModel( + allXp, + count, + monster.JsonMonster.Name, + GetTranslation(monster.JsonMonster.Type), + difficulty.GetName(Resources.Enum.ResourceManager), + monster.JsonMonster.ChallengeRating, + GetTranslation(monster.JsonMonster.Size), + monster.JsonMonster.Alignment ?? string.Empty, + monster.JsonMonster.HitPoints ?? 0, + monster.JsonMonster.ArmorClass ?? 0, + monster.JsonMonster.HitDice ?? string.Empty, + monster.JsonMonster.Speed ?? string.Empty, + monster.JsonMonster.Senses ?? string.Empty, + monster.JsonMonster.Languages ?? string.Empty, + monster.JsonMonster.Strength ?? 0, + monster.JsonMonster.Dexterity ?? 0, + monster.JsonMonster.Constitution ?? 0, + monster.JsonMonster.Intelligence ?? 0, + monster.JsonMonster.Wisdom ?? 0, + monster.JsonMonster.Charisma ?? 0, + monster.JsonMonster.StrengthSave ?? 0, + monster.JsonMonster.DexteritySave ?? 0, + monster.JsonMonster.ConstitutionSave ?? 0, + monster.JsonMonster.IntelligenceSave ?? 0, + monster.JsonMonster.WisdomSave ?? 0, + monster.JsonMonster.CharismaSave ?? 0, + monster.JsonMonster.History ?? 0, + monster.JsonMonster.Perception ?? 0, + monster.JsonMonster.DamageVulnerabilities, + monster.JsonMonster.DamageResistances, + monster.JsonMonster.DamageImmunities, + monster.JsonMonster.ConditionImmunities, + monster.JsonMonster.SpecialAbilities?.ToArray() ?? [], + monster.JsonMonster.Actions?.ToArray() ?? [], + monster.JsonMonster.LegendaryActions?.ToArray() ?? [], + monster.JsonMonster.Reactions?.ToArray() ?? [] + ), + monster.Id, + monster.Timestamp, + monster.CreatedBy, + monster.Created, + monster.LastModifiedBy, + monster.LastModified + ); + } + + public MonsterModel ToModel() + { + return new MonsterModel( + new JsonMonsterModel( + 0, + 0, + monster.JsonMonster.Name, + GetTranslation(monster.JsonMonster.Type), + string.Empty, + monster.JsonMonster.ChallengeRating, + GetTranslation(monster.JsonMonster.Size), + monster.JsonMonster.Alignment ?? string.Empty, + monster.JsonMonster.HitPoints ?? 0, + monster.JsonMonster.ArmorClass ?? 0, + monster.JsonMonster.HitDice ?? string.Empty, + monster.JsonMonster.Speed ?? string.Empty, + monster.JsonMonster.Senses ?? string.Empty, + monster.JsonMonster.Languages ?? string.Empty, + monster.JsonMonster.Strength ?? 0, + monster.JsonMonster.Dexterity ?? 0, + monster.JsonMonster.Constitution ?? 0, + monster.JsonMonster.Intelligence ?? 0, + monster.JsonMonster.Wisdom ?? 0, + monster.JsonMonster.Charisma ?? 0, + monster.JsonMonster.StrengthSave ?? 0, + monster.JsonMonster.DexteritySave ?? 0, + monster.JsonMonster.ConstitutionSave ?? 0, + monster.JsonMonster.IntelligenceSave ?? 0, + monster.JsonMonster.WisdomSave ?? 0, + monster.JsonMonster.CharismaSave ?? 0, + monster.JsonMonster.History ?? 0, + monster.JsonMonster.Perception ?? 0, + monster.JsonMonster.DamageVulnerabilities, + monster.JsonMonster.DamageResistances, + monster.JsonMonster.DamageImmunities, + monster.JsonMonster.ConditionImmunities, + monster.JsonMonster.SpecialAbilities?.ToArray() ?? [], + monster.JsonMonster.Actions?.ToArray() ?? [], + monster.JsonMonster.LegendaryActions?.ToArray() ?? [], + monster.JsonMonster.Reactions?.ToArray() ?? [] + ), + monster.Id, + monster.Timestamp, + monster.CreatedBy, + monster.Created, + monster.LastModifiedBy, + monster.LastModified + ); + } + } + + private static string GetTranslation(string original) where T : struct, Enum + { + string? translation = null; + if (Enum.TryParse(original, out T type)) + translation = type.GetName(Resources.Enum.ResourceManager); + return translation ?? original; + } +} \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Mappers/OptionMapper.cs b/src/Open5ETools.Core/Common/Mappers/OptionMapper.cs new file mode 100644 index 0000000..cd424e0 --- /dev/null +++ b/src/Open5ETools.Core/Common/Mappers/OptionMapper.cs @@ -0,0 +1,17 @@ +using Open5ETools.Core.Common.Models.DM.Services; +using Open5ETools.Core.Domain.DM; + +namespace Open5ETools.Core.Common.Mappers; + +public static class OptionMapper +{ + public static OptionModel ToModel(this Option option) + { + return new OptionModel + ( + option.Key, + option.Name, + option.Value + ); + } +} \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Mappers/SpellMapper.cs b/src/Open5ETools.Core/Common/Mappers/SpellMapper.cs new file mode 100644 index 0000000..3aa5566 --- /dev/null +++ b/src/Open5ETools.Core/Common/Mappers/SpellMapper.cs @@ -0,0 +1,74 @@ +using Open5ETools.Core.Common.Enums.SM; +using Open5ETools.Core.Common.Models.SM; +using Open5ETools.Core.Domain.SM; + +namespace Open5ETools.Core.Common.Mappers; + +public static class SpellMapper +{ + public static SpellModel ToModel(this Spell spell) + { + return new SpellModel + ( + spell.Name, + spell.Desc, + spell.HigherLevel, + spell.Page, + spell.Range, + spell.Components, + spell.Material, + spell.Ritual, + spell.Duration, + spell.Concentration, + spell.CastingTime, + spell.Level, + spell.School, + spell.Class, + spell.Archetype, + spell.Circles, + spell.Domains, + spell.Oaths, + spell.Patrons, + spell.Id, + spell.Timestamp, + spell.CreatedBy, + spell.Created, + spell.LastModifiedBy, + spell.LastModified + ); + } + + public static Spell ToEntity(this Open5ETools.Core.Common.Models.Json.Spell spell) + { + return new Spell + { + Name = spell.Name, + Desc = spell.Desc, + HigherLevel = spell.HigherLevel, + Page = spell.Page, + Range = spell.Range ?? string.Empty, + Components = spell.Components ?? string.Empty, + Material = spell.Material, + Ritual = ConvertToBool(spell.Ritual), + Duration = spell.Duration, + Concentration = ConvertToBool(spell.Concentration), + CastingTime = spell.CastingTime ?? string.Empty, + Level = spell.Level, + School = Enum.Parse(spell.School ?? string.Empty), + Class = spell.Class ?? string.Empty, + Archetype = spell.Archetype, + Circles = spell.Circles, + Domains = spell.Domains, + Oaths = spell.Oaths, + Patrons = spell.Patrons, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty + }; + } + + private static bool ConvertToBool(string? property) + { + return string.IsNullOrWhiteSpace(property) || + !property.Equals("no", StringComparison.InvariantCultureIgnoreCase); + } +} \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Mappers/UserMapper.cs b/src/Open5ETools.Core/Common/Mappers/UserMapper.cs new file mode 100644 index 0000000..1bc4a88 --- /dev/null +++ b/src/Open5ETools.Core/Common/Mappers/UserMapper.cs @@ -0,0 +1,48 @@ +using Open5ETools.Core.Common.Enums; +using Open5ETools.Core.Common.Models.Services; +using Open5ETools.Core.Domain; + +namespace Open5ETools.Core.Common.Mappers; + +public static class UserMapper +{ + public static UserModel ToModel(this User user) + { + return new UserModel + ( + user.Username, + user.FirstName, + user.LastName, + user.Email, + user.Password, + user.IsDeleted, + user.Role.ToString(), + user.Id, + user.Timestamp, + user.CreatedBy, + user.Created, + user.LastModifiedBy, + user.LastModified + ); + } + + public static User ToEntity(this UserModel user) + { + return new User + { + Username = user.Username, + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Password = user.Password, + IsDeleted = user.IsDeleted, + Role = Enum.Parse(user.Role), + Id = user.Id, + Timestamp = user.Timestamp, + CreatedBy = user.CreatedBy, + Created = user.Created, + LastModifiedBy = user.LastModifiedBy, + LastModified = user.LastModified + }; + } +} \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/DM/Generator/TreasureDescription.cs b/src/Open5ETools.Core/Common/Models/DM/Generator/TreasureDescription.cs index 805d6d4..d5c12b2 100644 --- a/src/Open5ETools.Core/Common/Models/DM/Generator/TreasureDescription.cs +++ b/src/Open5ETools.Core/Common/Models/DM/Generator/TreasureDescription.cs @@ -5,5 +5,5 @@ public record TreasureDescription( int Cost, int Rarity, bool Magical, - IReadOnlyCollection Types + string[] Types ); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/DM/Services/DungeonModel.cs b/src/Open5ETools.Core/Common/Models/DM/Services/DungeonModel.cs index 10fc870..545c6ff 100644 --- a/src/Open5ETools.Core/Common/Models/DM/Services/DungeonModel.cs +++ b/src/Open5ETools.Core/Common/Models/DM/Services/DungeonModel.cs @@ -2,12 +2,17 @@ namespace Open5ETools.Core.Common.Models.DM.Services; -public class DungeonModel : EditModel -{ - public string DungeonTiles { get; set; } = string.Empty; - public string RoomDescription { get; set; } = string.Empty; - public string TrapDescription { get; set; } = string.Empty; - public string? RoamingMonsterDescription { get; set; } - public int DungeonOptionId { get; set; } - public int Level { get; set; } -} \ No newline at end of file +public record DungeonModel( + string DungeonTiles, + string RoomDescription, + string TrapDescription, + string? RoamingMonsterDescription, + int DungeonOptionId, + int Level, + int Id, + byte[] Timestamp, + string CreatedBy, + DateTime Created, + string LastModifiedBy, + DateTime LastModified +) : EditModel(Id, Timestamp, CreatedBy, Created, LastModifiedBy, LastModified); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/DM/Services/DungeonOptionModel.cs b/src/Open5ETools.Core/Common/Models/DM/Services/DungeonOptionModel.cs index d43d472..91af7cb 100644 --- a/src/Open5ETools.Core/Common/Models/DM/Services/DungeonOptionModel.cs +++ b/src/Open5ETools.Core/Common/Models/DM/Services/DungeonOptionModel.cs @@ -2,24 +2,29 @@ namespace Open5ETools.Core.Common.Models.DM.Services; -public class DungeonOptionModel : EditModel -{ - public string DungeonName { get; set; } = string.Empty; - public int UserId { get; set; } - public int DungeonSize { get; set; } - public int DungeonDifficulty { get; set; } - public int PartyLevel { get; set; } - public int PartySize { get; set; } - public double TreasureValue { get; set; } - public int ItemsRarity { get; set; } - public int RoomDensity { get; set; } - public int RoomSize { get; set; } - public string MonsterType { get; set; } = string.Empty; - public int TrapPercent { get; set; } - public bool DeadEnd { get; set; } - public bool Corridor { get; set; } - public int RoamingPercent { get; set; } - public int Width { get; set; } = 800; - public int Height { get; set; } = 800; - public IEnumerable Dungeons { get; set; } = []; -} \ No newline at end of file +public record DungeonOptionModel( + string DungeonName, + int UserId, + int DungeonSize, + int DungeonDifficulty, + int PartyLevel, + int PartySize, + double TreasureValue, + int ItemsRarity, + int RoomDensity, + int RoomSize, + string MonsterType, + int TrapPercent, + bool DeadEnd, + bool Corridor, + int RoamingPercent, + DungeonModel[] Dungeons, + int Id, + byte[] Timestamp, + string CreatedBy, + DateTime Created, + string LastModifiedBy, + DateTime LastModified, + int Width = 800, + int Height = 800 +) : EditModel(Id, Timestamp, CreatedBy, Created, LastModifiedBy, LastModified); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/DM/Services/OptionModel.cs b/src/Open5ETools.Core/Common/Models/DM/Services/OptionModel.cs index 9eff163..cf21afe 100644 --- a/src/Open5ETools.Core/Common/Models/DM/Services/OptionModel.cs +++ b/src/Open5ETools.Core/Common/Models/DM/Services/OptionModel.cs @@ -2,9 +2,8 @@ namespace Open5ETools.Core.Common.Models.DM.Services; -public class OptionModel -{ - public OptionKey Key { get; set; } - public string Name { get; set; } = string.Empty; - public string Value { get; set; } = string.Empty; -} \ No newline at end of file +public record OptionModel( + OptionKey Key, + string Name, + string Value +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/EG/EncounterDetail.cs b/src/Open5ETools.Core/Common/Models/EG/EncounterDetail.cs index 4cf89c6..aa2a78d 100644 --- a/src/Open5ETools.Core/Common/Models/EG/EncounterDetail.cs +++ b/src/Open5ETools.Core/Common/Models/EG/EncounterDetail.cs @@ -1,44 +1,42 @@ using Open5ETools.Core.Common.Models.Json; -using Open5ETools.Core.Common.Models.Services; namespace Open5ETools.Core.Common.Models.EG; -public class EncounterDetail : EditModel -{ - public int Xp { get; set; } - public int Count { get; set; } - public string Name { get; set; } = string.Empty; - public string Type { get; set; } = string.Empty; - public string Difficulty { get; set; } = string.Empty; - public string ChallengeRating { get; set; } = string.Empty; - public string Size { get; set; } = string.Empty; - public string Alignment { get; set; } = string.Empty; - public int Hp { get; set; } - public int Ac { get; set; } - public string HitDice { get; set; } = string.Empty; - public string Speed { get; set; } = string.Empty; - public string? Senses { get; set; } - public string? Languages { get; set; } - public int Strength { get; set; } - public int Dexterity { get; set; } - public int Constitution { get; set; } - public int Intelligence { get; set; } - public int Wisdom { get; set; } - public int Charisma { get; set; } - public int StrengthSave { get; set; } - public int DexteritySave { get; set; } - public int ConstitutionSave { get; set; } - public int IntelligenceSave { get; set; } - public int WisdomSave { get; set; } - public int CharismaSave { get; set; } - public int History { get; set; } - public int Perception { get; set; } - public string? DamageVulnerabilities { get; set; } - public string? DamageResistances { get; set; } - public string? DamageImmunities { get; set; } - public string? ConditionImmunities { get; set; } - public List SpecialAbilities { get; set; } = []; - public List Actions { get; set; } = []; - public List LegendaryActions { get; set; } = []; - public List Reactions { get; set; } = []; -} \ No newline at end of file +public record EncounterDetail( + int Xp, + int Count, + string Name, + string Type, + string Difficulty, + string ChallengeRating, + string Size, + string Alignment, + int Hp, + int Ac, + string HitDice, + string Speed, + string Senses, + string Languages, + int Strength, + int Dexterity, + int Constitution, + int Intelligence, + int Wisdom, + int Charisma, + int StrengthSave, + int DexteritySave, + int ConstitutionSave, + int IntelligenceSave, + int WisdomSave, + int CharismaSave, + int History, + int Perception, + string? DamageVulnerabilities, + string? DamageResistances, + string? DamageImmunities, + string? ConditionImmunities, + SpecialAbility[] SpecialAbilities, + Json.Action[] Actions, + LegendaryAction[] LegendaryActions, + Reaction[] Reactions +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/EG/EncounterModel.cs b/src/Open5ETools.Core/Common/Models/EG/EncounterModel.cs index 6cd74d4..b2a1515 100644 --- a/src/Open5ETools.Core/Common/Models/EG/EncounterModel.cs +++ b/src/Open5ETools.Core/Common/Models/EG/EncounterModel.cs @@ -1,7 +1,6 @@ namespace Open5ETools.Core.Common.Models.EG; -public class EncounterModel -{ - public int SumXp { get; set; } - public List Monsters { get; set; } = []; -} \ No newline at end of file +public record EncounterModel +( + MonsterModel[] Monsters +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/EG/EncounterOption.cs b/src/Open5ETools.Core/Common/Models/EG/EncounterOption.cs index c2e1753..3645063 100644 --- a/src/Open5ETools.Core/Common/Models/EG/EncounterOption.cs +++ b/src/Open5ETools.Core/Common/Models/EG/EncounterOption.cs @@ -1,14 +1,12 @@ using Open5ETools.Core.Common.Enums.EG; -using Open5ETools.Core.Common.Models.Services; namespace Open5ETools.Core.Common.Models.EG; -public class EncounterOption : EditModel -{ - public int PartyLevel { get; set; } - public int PartySize { get; set; } - public Difficulty? Difficulty { get; set; } - public IEnumerable MonsterTypes { get; set; } = []; - public IEnumerable Sizes { get; set; } = []; - public int Count { get; set; } = 10; -} \ No newline at end of file +public record EncounterOption( + int PartyLevel, + int PartySize, + Difficulty? Difficulty, + MonsterType[] MonsterTypes, + Size[] Sizes, + int Count = 10 +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/EG/JsonMonsterModel.cs b/src/Open5ETools.Core/Common/Models/EG/JsonMonsterModel.cs index 17bd80d..8568a14 100644 --- a/src/Open5ETools.Core/Common/Models/EG/JsonMonsterModel.cs +++ b/src/Open5ETools.Core/Common/Models/EG/JsonMonsterModel.cs @@ -2,42 +2,41 @@ namespace Open5ETools.Core.Common.Models.EG; -public class JsonMonsterModel -{ - public int Xp { get; set; } - public int Count { get; set; } - public string Name { get; set; } = string.Empty; - public string Type { get; set; } = string.Empty; - public string Difficulty { get; set; } = string.Empty; - public string ChallengeRating { get; set; } = string.Empty; - public string Size { get; set; } = string.Empty; - public string Alignment { get; set; } = string.Empty; - public int Hp { get; set; } - public int Ac { get; set; } - public string HitDice { get; set; } = string.Empty; - public string Speed { get; set; } = string.Empty; - public string? Senses { get; set; } - public string? Languages { get; set; } - public int Strength { get; set; } - public int Dexterity { get; set; } - public int Constitution { get; set; } - public int Intelligence { get; set; } - public int Wisdom { get; set; } - public int Charisma { get; set; } - public int StrengthSave { get; set; } - public int DexteritySave { get; set; } - public int ConstitutionSave { get; set; } - public int IntelligenceSave { get; set; } - public int WisdomSave { get; set; } - public int CharismaSave { get; set; } - public int History { get; set; } - public int Perception { get; set; } - public string? DamageVulnerabilities { get; set; } - public string? DamageResistances { get; set; } - public string? DamageImmunities { get; set; } - public string? ConditionImmunities { get; set; } - public List SpecialAbilities { get; set; } = []; - public List Actions { get; set; } = []; - public List LegendaryActions { get; set; } = []; - public List Reactions { get; set; } = []; -} \ No newline at end of file +public record JsonMonsterModel( + int Xp, + int Count, + string Name, + string Type, + string Difficulty, + string ChallengeRating, + string Size, + string Alignment, + int Hp, + int Ac, + string HitDice, + string Speed, + string? Senses, + string? Languages, + int Strength, + int Dexterity, + int Constitution, + int Intelligence, + int Wisdom, + int Charisma, + int StrengthSave, + int DexteritySave, + int ConstitutionSave, + int IntelligenceSave, + int WisdomSave, + int CharismaSave, + int History, + int Perception, + string? DamageVulnerabilities, + string? DamageResistances, + string? DamageImmunities, + string? ConditionImmunities, + SpecialAbility[] SpecialAbilities, + Json.Action[] Actions, + LegendaryAction[] LegendaryActions, + Reaction[] Reactions +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/EG/MonsterModel.cs b/src/Open5ETools.Core/Common/Models/EG/MonsterModel.cs index 553771f..0858313 100644 --- a/src/Open5ETools.Core/Common/Models/EG/MonsterModel.cs +++ b/src/Open5ETools.Core/Common/Models/EG/MonsterModel.cs @@ -2,7 +2,13 @@ namespace Open5ETools.Core.Common.Models.EG; -public class MonsterModel : EditModel -{ - public JsonMonsterModel JsonMonsterModel { get; set; } = new(); -} \ No newline at end of file +public record MonsterModel +( + JsonMonsterModel JsonMonsterModel, + int Id, + byte[] Timestamp, + string CreatedBy, + DateTime Created, + string LastModifiedBy, + DateTime LastModified +) : EditModel(Id, Timestamp, CreatedBy, Created, LastModifiedBy, LastModified); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Json/Action.cs b/src/Open5ETools.Core/Common/Models/Json/Action.cs index 66df3a0..66226e4 100644 --- a/src/Open5ETools.Core/Common/Models/Json/Action.cs +++ b/src/Open5ETools.Core/Common/Models/Json/Action.cs @@ -2,20 +2,13 @@ namespace Open5ETools.Core.Common.Models.Json; -public class Action -{ - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("desc")] - public string? Desc { get; set; } - - [JsonPropertyName("attack_bonus")] - public int? AttackBonus { get; set; } - - [JsonPropertyName("damage_dice")] - public string? DamageDice { get; set; } - - [JsonPropertyName("damage_bonus")] - public int? DamageBonus { get; set; } -} \ No newline at end of file +public record Action( + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("desc")] string? Desc, + [property: JsonPropertyName("attack_bonus")] + int? AttackBonus, + [property: JsonPropertyName("damage_dice")] + string? DamageDice, + [property: JsonPropertyName("damage_bonus")] + int? DamageBonus +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Json/LegendaryAction.cs b/src/Open5ETools.Core/Common/Models/Json/LegendaryAction.cs index aac2dea..62b9cfa 100644 --- a/src/Open5ETools.Core/Common/Models/Json/LegendaryAction.cs +++ b/src/Open5ETools.Core/Common/Models/Json/LegendaryAction.cs @@ -2,17 +2,9 @@ namespace Open5ETools.Core.Common.Models.Json; -public class LegendaryAction -{ - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("desc")] - public string? Desc { get; set; } - - [JsonPropertyName("attack_bonus")] - public int? AttackBonus { get; set; } - - [JsonPropertyName("damage_dice")] - public string? DamageDice { get; set; } -} \ No newline at end of file +public record LegendaryAction( + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("desc")] string? Desc, + [property: JsonPropertyName("attack_bonus")] int? AttackBonus, + [property: JsonPropertyName("damage_dice")] string? DamageDice +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Json/Monster.cs b/src/Open5ETools.Core/Common/Models/Json/Monster.cs index 5a16ab5..8f904e0 100644 --- a/src/Open5ETools.Core/Common/Models/Json/Monster.cs +++ b/src/Open5ETools.Core/Common/Models/Json/Monster.cs @@ -2,149 +2,93 @@ namespace Open5ETools.Core.Common.Models.Json; -public class Monster -{ - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("size")] - public string Size { get; set; } = string.Empty; - - [JsonPropertyName("type")] - public string Type { get; set; } = string.Empty; - - [JsonPropertyName("subtype")] - public string? Subtype { get; set; } - - [JsonPropertyName("alignment")] - public string? Alignment { get; set; } - - [JsonPropertyName("armor_class")] - public int? ArmorClass { get; set; } - - [JsonPropertyName("hit_points")] - public int? HitPoints { get; set; } - - [JsonPropertyName("hit_dice")] - public string? HitDice { get; set; } - - [JsonPropertyName("speed")] - public string? Speed { get; set; } - - [JsonPropertyName("strength")] - public int? Strength { get; set; } - - [JsonPropertyName("dexterity")] - public int? Dexterity { get; set; } - - [JsonPropertyName("constitution")] - public int? Constitution { get; set; } - - [JsonPropertyName("intelligence")] - public int? Intelligence { get; set; } - - [JsonPropertyName("wisdom")] - public int? Wisdom { get; set; } - - [JsonPropertyName("charisma")] - public int? Charisma { get; set; } - - [JsonPropertyName("constitution_save")] - public int? ConstitutionSave { get; set; } - - [JsonPropertyName("intelligence_save")] - public int? IntelligenceSave { get; set; } - - [JsonPropertyName("wisdom_save")] - public int? WisdomSave { get; set; } - - [JsonPropertyName("history")] - public int? History { get; set; } - - [JsonPropertyName("perception")] - public int? Perception { get; set; } - - [JsonPropertyName("damage_vulnerabilities")] - public string? DamageVulnerabilities { get; set; } - - [JsonPropertyName("damage_resistances")] - public string? DamageResistances { get; set; } - - [JsonPropertyName("damage_immunities")] - public string? DamageImmunities { get; set; } - - [JsonPropertyName("condition_immunities")] - public string? ConditionImmunities { get; set; } - - [JsonPropertyName("senses")] - public string? Senses { get; set; } - - [JsonPropertyName("languages")] - public string? Languages { get; set; } - - [JsonPropertyName("challenge_rating")] - public string ChallengeRating { get; set; } = string.Empty; - - [JsonPropertyName("special_abilities")] - public List? SpecialAbilities { get; set; } - - [JsonPropertyName("actions")] - public List? Actions { get; set; } - - [JsonPropertyName("legendary_actions")] - public List? LegendaryActions { get; set; } - - [JsonPropertyName("medicine")] - public int? Medicine { get; set; } - - [JsonPropertyName("religion")] - public int? Religion { get; set; } - - [JsonPropertyName("dexterity_save")] - public int? DexteritySave { get; set; } - - [JsonPropertyName("charisma_save")] - public int? CharismaSave { get; set; } - - [JsonPropertyName("stealth")] - public int? Stealth { get; set; } - - [JsonPropertyName("persuasion")] - public int? Persuasion { get; set; } - - [JsonPropertyName("insight")] - public int? Insight { get; set; } - - [JsonPropertyName("deception")] - public int? Deception { get; set; } - - [JsonPropertyName("arcana")] - public int? Arcana { get; set; } - - [JsonPropertyName("athletics")] - public int? Athletics { get; set; } - - [JsonPropertyName("acrobatics")] - public int? Acrobatics { get; set; } - - [JsonPropertyName("strength_save")] - public int? StrengthSave { get; set; } - - [JsonPropertyName("reactions")] - public List? Reactions { get; set; } - - [JsonPropertyName("survival")] - public int? Survival { get; set; } - - [JsonPropertyName("investigation")] - public int? Investigation { get; set; } - - [JsonPropertyName("nature")] - public int? Nature { get; set; } - - [JsonPropertyName("intimidation")] - public int? Intimidation { get; set; } - - [JsonPropertyName("performance")] - public int? Performance { get; set; } -} \ No newline at end of file +public record Monster( + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("size")] string Size, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("subtype")] + string? Subtype, + [property: JsonPropertyName("alignment")] + string? Alignment, + [property: JsonPropertyName("armor_class")] + int? ArmorClass, + [property: JsonPropertyName("hit_points")] + int? HitPoints, + [property: JsonPropertyName("hit_dice")] + string? HitDice, + [property: JsonPropertyName("speed")] string? Speed, + [property: JsonPropertyName("strength")] + int? Strength, + [property: JsonPropertyName("dexterity")] + int? Dexterity, + [property: JsonPropertyName("constitution")] + int? Constitution, + [property: JsonPropertyName("intelligence")] + int? Intelligence, + [property: JsonPropertyName("wisdom")] int? Wisdom, + [property: JsonPropertyName("charisma")] + int? Charisma, + [property: JsonPropertyName("constitution_save")] + int? ConstitutionSave, + [property: JsonPropertyName("intelligence_save")] + int? IntelligenceSave, + [property: JsonPropertyName("wisdom_save")] + int? WisdomSave, + [property: JsonPropertyName("history")] + int? History, + [property: JsonPropertyName("perception")] + int? Perception, + [property: JsonPropertyName("damage_vulnerabilities")] + string? DamageVulnerabilities, + [property: JsonPropertyName("damage_resistances")] + string? DamageResistances, + [property: JsonPropertyName("damage_immunities")] + string? DamageImmunities, + [property: JsonPropertyName("condition_immunities")] + string? ConditionImmunities, + [property: JsonPropertyName("senses")] string? Senses, + [property: JsonPropertyName("languages")] + string? Languages, + [property: JsonPropertyName("challenge_rating")] + string ChallengeRating, + [property: JsonPropertyName("special_abilities")] + List? SpecialAbilities, + [property: JsonPropertyName("actions")] + List? Actions, + [property: JsonPropertyName("legendary_actions")] + List? LegendaryActions, + [property: JsonPropertyName("medicine")] + int? Medicine, + [property: JsonPropertyName("religion")] + int? Religion, + [property: JsonPropertyName("dexterity_save")] + int? DexteritySave, + [property: JsonPropertyName("charisma_save")] + int? CharismaSave, + [property: JsonPropertyName("stealth")] + int? Stealth, + [property: JsonPropertyName("persuasion")] + int? Persuasion, + [property: JsonPropertyName("insight")] + int? Insight, + [property: JsonPropertyName("deception")] + int? Deception, + [property: JsonPropertyName("arcana")] int? Arcana, + [property: JsonPropertyName("athletics")] + int? Athletics, + [property: JsonPropertyName("acrobatics")] + int? Acrobatics, + [property: JsonPropertyName("strength_save")] + int? StrengthSave, + [property: JsonPropertyName("reactions")] + List? Reactions, + [property: JsonPropertyName("survival")] + int? Survival, + [property: JsonPropertyName("investigation")] + int? Investigation, + [property: JsonPropertyName("nature")] int? Nature, + [property: JsonPropertyName("intimidation")] + int? Intimidation, + [property: JsonPropertyName("performance")] + int? Performance +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Json/Reaction.cs b/src/Open5ETools.Core/Common/Models/Json/Reaction.cs index 876135a..abbcfb7 100644 --- a/src/Open5ETools.Core/Common/Models/Json/Reaction.cs +++ b/src/Open5ETools.Core/Common/Models/Json/Reaction.cs @@ -2,14 +2,9 @@ namespace Open5ETools.Core.Common.Models.Json; -public class Reaction -{ - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("desc")] - public string? Desc { get; set; } - - [JsonPropertyName("attack_bonus")] - public int? AttackBonus { get; set; } -} \ No newline at end of file +public record Reaction( + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("desc")] string? Desc, + [property: JsonPropertyName("attack_bonus")] + int? AttackBonus +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Json/SpecialAbility.cs b/src/Open5ETools.Core/Common/Models/Json/SpecialAbility.cs index 9f3b652..fe9206a 100644 --- a/src/Open5ETools.Core/Common/Models/Json/SpecialAbility.cs +++ b/src/Open5ETools.Core/Common/Models/Json/SpecialAbility.cs @@ -2,17 +2,11 @@ namespace Open5ETools.Core.Common.Models.Json; -public class SpecialAbility -{ - [JsonPropertyName("name")] - public string? Name { get; set; } - - [JsonPropertyName("desc")] - public string? Desc { get; set; } - - [JsonPropertyName("attack_bonus")] - public int? AttackBonus { get; set; } - - [JsonPropertyName("damage_dice")] - public string? DamageDice { get; set; } -} \ No newline at end of file +public record SpecialAbility( + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("desc")] string? Desc, + [property: JsonPropertyName("attack_bonus")] + int? AttackBonus, + [property: JsonPropertyName("damage_dice")] + string? DamageDice +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Json/Spell.cs b/src/Open5ETools.Core/Common/Models/Json/Spell.cs index e554db7..b832db7 100644 --- a/src/Open5ETools.Core/Common/Models/Json/Spell.cs +++ b/src/Open5ETools.Core/Common/Models/Json/Spell.cs @@ -1,62 +1,35 @@ using System.Text.Json.Serialization; namespace Open5ETools.Core.Common.Models.Json; -public class Spell -{ - [JsonPropertyName("name")] - public string Name { get; set; } = string.Empty; - [JsonPropertyName("desc")] - public string Desc { get; set; } = string.Empty; - - [JsonPropertyName("higher_level")] - public string? HigherLevel { get; set; } - - [JsonPropertyName("page")] - public string Page { get; set; } = string.Empty; - - [JsonPropertyName("range")] - public string? Range { get; set; } - - [JsonPropertyName("components")] - public string? Components { get; set; } - - [JsonPropertyName("material")] - public string? Material { get; set; } - - [JsonPropertyName("ritual")] - public string? Ritual { get; set; } - - [JsonPropertyName("duration")] - public string? Duration { get; set; } - - [JsonPropertyName("concentration")] - public string? Concentration { get; set; } - - [JsonPropertyName("casting_time")] - public string? CastingTime { get; set; } - - [JsonPropertyName("level")] - public string Level { get; set; } = string.Empty; - - [JsonPropertyName("school")] - public string? School { get; set; } - - [JsonPropertyName("class")] - public string? Class { get; set; } - - [JsonPropertyName("archetype")] - public string? Archetype { get; set; } - - [JsonPropertyName("circles")] - public string? Circles { get; set; } - - [JsonPropertyName("domains")] - public string? Domains { get; set; } - - [JsonPropertyName("oaths")] - public string? Oaths { get; set; } - - [JsonPropertyName("patrons")] - public string? Patrons { get; set; } -} \ No newline at end of file +public record Spell( + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("desc")] string Desc, + [property: JsonPropertyName("higher_level")] + string? HigherLevel, + [property: JsonPropertyName("page")] string Page, + [property: JsonPropertyName("range")] string? Range, + [property: JsonPropertyName("components")] + string? Components, + [property: JsonPropertyName("material")] + string? Material, + [property: JsonPropertyName("ritual")] string? Ritual, + [property: JsonPropertyName("duration")] + string? Duration, + [property: JsonPropertyName("concentration")] + string? Concentration, + [property: JsonPropertyName("casting_time")] + string? CastingTime, + [property: JsonPropertyName("level")] string Level, + [property: JsonPropertyName("school")] string? School, + [property: JsonPropertyName("class")] string? Class, + [property: JsonPropertyName("archetype")] + string? Archetype, + [property: JsonPropertyName("circles")] + string? Circles, + [property: JsonPropertyName("domains")] + string? Domains, + [property: JsonPropertyName("oaths")] string? Oaths, + [property: JsonPropertyName("patrons")] + string? Patrons +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/SM/SpellModel.cs b/src/Open5ETools.Core/Common/Models/SM/SpellModel.cs index 3bf79ae..cc7ce8e 100644 --- a/src/Open5ETools.Core/Common/Models/SM/SpellModel.cs +++ b/src/Open5ETools.Core/Common/Models/SM/SpellModel.cs @@ -3,43 +3,30 @@ namespace Open5ETools.Core.Common.Models.SM; -public class SpellModel: EditModel -{ - public string Name { get; set; } = string.Empty; - - public string Desc { get; set; } = string.Empty; - - public string? HigherLevel { get; set; } - - public string Page { get; set; } = string.Empty; - - public string Range { get; set; } = string.Empty; - - public string Components { get; set; } = string.Empty; - - public string? Material { get; set; } - - public bool Ritual { get; set; } - - public string? Duration { get; set; } - - public bool Concentration { get; set; } - - public string CastingTime { get; set; } = string.Empty; - - public string Level { get; set; } = string.Empty; - - public School School { get; set; } - - public string Class { get; set; } = string.Empty; - - public string? Archetype { get; set; } - - public string? Circles { get; set; } - - public string? Domains { get; set; } - - public string? Oaths { get; set; } - - public string? Patrons { get; set; } -} +public record SpellModel( + string Name, + string Desc, + string? HigherLevel, + string Page, + string Range, + string Components, + string? Material, + bool Ritual, + string? Duration, + bool Concentration, + string CastingTime, + string Level, + School School, + string Class, + string? Archetype, + string? Circles, + string? Domains, + string? Oaths, + string? Patrons, + int Id, + byte[] Timestamp, + string CreatedBy, + DateTime Created, + string LastModifiedBy, + DateTime LastModified +) : EditModel(Id, Timestamp, CreatedBy, Created, LastModifiedBy, LastModified); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Services/ChangePasswordModel.cs b/src/Open5ETools.Core/Common/Models/Services/ChangePasswordModel.cs index 9e73701..6ba9fe7 100644 --- a/src/Open5ETools.Core/Common/Models/Services/ChangePasswordModel.cs +++ b/src/Open5ETools.Core/Common/Models/Services/ChangePasswordModel.cs @@ -1,8 +1,7 @@ namespace Open5ETools.Core.Common.Models.Services; -public class ChangePasswordModel -{ - public int Id { get; set; } - public string CurrentPassword { get; set; } = string.Empty; - public string NewPassword { get; set; } = string.Empty; -} \ No newline at end of file +public record ChangePasswordModel( + int Id, + string CurrentPassword, + string NewPassword +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Services/EditModel.cs b/src/Open5ETools.Core/Common/Models/Services/EditModel.cs index 15560cd..0992dc5 100644 --- a/src/Open5ETools.Core/Common/Models/Services/EditModel.cs +++ b/src/Open5ETools.Core/Common/Models/Services/EditModel.cs @@ -1,14 +1,10 @@ namespace Open5ETools.Core.Common.Models.Services; -public class EditModel -{ - public int Id { get; set; } - public byte[] Timestamp { get; set; } = []; - public string CreatedBy { get; set; } = string.Empty; - - public DateTime Created { get; set; } - - public string LastModifiedBy { get; set; } = string.Empty; - - public DateTime LastModified { get; set; } -} \ No newline at end of file +public record EditModel( + int Id, + byte[] Timestamp, + string CreatedBy, + DateTime Created, + string LastModifiedBy, + DateTime LastModified +); \ No newline at end of file diff --git a/src/Open5ETools.Core/Common/Models/Services/UserModel.cs b/src/Open5ETools.Core/Common/Models/Services/UserModel.cs index 077dda2..a41042a 100644 --- a/src/Open5ETools.Core/Common/Models/Services/UserModel.cs +++ b/src/Open5ETools.Core/Common/Models/Services/UserModel.cs @@ -1,12 +1,17 @@ namespace Open5ETools.Core.Common.Models.Services; -public class UserModel : EditModel -{ - public string Username { get; set; } = string.Empty; - public string FirstName { get; set; } = string.Empty; - public string LastName { get; set; } = string.Empty; - public string Email { get; set; } = string.Empty; - public string Password { get; set; } = string.Empty; - public bool IsDeleted { get; set; } - public string Role { get; set; } = string.Empty; -} \ No newline at end of file +public record UserModel( + string Username, + string FirstName, + string LastName, + string Email, + string Password, + bool IsDeleted, + string Role, + int Id, + byte[] Timestamp, + string CreatedBy, + DateTime Created, + string LastModifiedBy, + DateTime LastModified +) : EditModel(Id, Timestamp, CreatedBy, Created, LastModifiedBy, LastModified); \ No newline at end of file diff --git a/src/Open5ETools.Core/ConfigureServices.cs b/src/Open5ETools.Core/ConfigureServices.cs index cc48fee..7885f46 100644 --- a/src/Open5ETools.Core/ConfigureServices.cs +++ b/src/Open5ETools.Core/ConfigureServices.cs @@ -1,14 +1,10 @@ -using Mapster; -using Microsoft.Extensions.DependencyInjection; -using Open5ETools.Core.Common.Enums.SM; +using Microsoft.Extensions.DependencyInjection; using Open5ETools.Core.Common.Helpers; using Open5ETools.Core.Common.Interfaces.Services; using Open5ETools.Core.Common.Interfaces.Services.DM; using Open5ETools.Core.Common.Interfaces.Services.DM.Generator; using Open5ETools.Core.Common.Interfaces.Services.EG; using Open5ETools.Core.Common.Interfaces.Services.SM; -using Open5ETools.Core.Common.Models.EG; -using Open5ETools.Core.Common.Models.Json; using Open5ETools.Core.Services; using Open5ETools.Core.Services.DM; using Open5ETools.Core.Services.DM.Generator; @@ -34,33 +30,6 @@ public IServiceCollection AddApplicationServices() .AddScoped() .AddScoped(); - services.ConfigureMapster(); - return services; - } - - private IServiceCollection ConfigureMapster() - { - services.AddMapster(); - TypeAdapterConfig - .NewConfig() - .Map(dest => dest.Concentration, - src => string.IsNullOrWhiteSpace(src.Concentration) || - !src.Concentration.Equals("no", StringComparison.InvariantCultureIgnoreCase)) - .Map(dest => dest.Ritual, - src => string.IsNullOrWhiteSpace(src.Ritual) || - !src.Ritual.Equals("no", StringComparison.InvariantCultureIgnoreCase)) - .Map(dest => dest.School, - src => Enum.Parse(src.School ?? string.Empty)); - - TypeAdapterConfig - .NewConfig() - .Map(dest => dest.Hp, src => src.HitPoints) - .Map(dest => dest.Ac, src => src.ArmorClass); - - TypeAdapterConfig - .NewConfig() - .Map(dest => dest.JsonMonsterModel, src => src.JsonMonster); - return services; } } diff --git a/src/Open5ETools.Core/Domain/AuditableEntity.cs b/src/Open5ETools.Core/Domain/AuditableEntity.cs index 1ad8dab..3844dbb 100644 --- a/src/Open5ETools.Core/Domain/AuditableEntity.cs +++ b/src/Open5ETools.Core/Domain/AuditableEntity.cs @@ -2,11 +2,8 @@ namespace Open5ETools.Core.Domain; public abstract class AuditableEntity : BaseEntity { - public string CreatedBy { get; set; } = string.Empty; - + public required string CreatedBy { get; set; } public DateTime Created { get; set; } - - public string LastModifiedBy { get; set; } = string.Empty; - + public required string LastModifiedBy { get; set; } public DateTime LastModified { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Core/Domain/DM/Dungeon.cs b/src/Open5ETools.Core/Domain/DM/Dungeon.cs index bcb2e36..e20d23e 100644 --- a/src/Open5ETools.Core/Domain/DM/Dungeon.cs +++ b/src/Open5ETools.Core/Domain/DM/Dungeon.cs @@ -1,11 +1,13 @@ +using System.ComponentModel.DataAnnotations; + namespace Open5ETools.Core.Domain.DM; public class Dungeon : AuditableEntity { - public string DungeonTiles { get; set; } = string.Empty; - public string RoomDescription { get; set; } = string.Empty; - public string TrapDescription { get; set; } = string.Empty; - public string? RoamingMonsterDescription { get; set; } + [StringLength(int.MaxValue)] public required string DungeonTiles { get; set; } + [StringLength(short.MaxValue)] public required string RoomDescription { get; set; } + [StringLength(short.MaxValue)] public required string TrapDescription { get; set; } + [StringLength(short.MaxValue)] public string? RoamingMonsterDescription { get; set; } public int Level { get; set; } public int DungeonOptionId { get; set; } public DungeonOption? DungeonOption { get; set; } diff --git a/src/Open5ETools.Core/Domain/DM/DungeonOption.cs b/src/Open5ETools.Core/Domain/DM/DungeonOption.cs index 68f0452..3d85ffb 100644 --- a/src/Open5ETools.Core/Domain/DM/DungeonOption.cs +++ b/src/Open5ETools.Core/Domain/DM/DungeonOption.cs @@ -1,8 +1,10 @@ +using System.ComponentModel.DataAnnotations; + namespace Open5ETools.Core.Domain.DM; public class DungeonOption : AuditableEntity { - public string DungeonName { get; set; } = string.Empty; + [StringLength(short.MaxValue)] public required string DungeonName { get; set; } public int DungeonSize { get; set; } public int DungeonDifficulty { get; set; } public int PartyLevel { get; set; } @@ -11,13 +13,12 @@ public class DungeonOption : AuditableEntity public int ItemsRarity { get; set; } public int RoomDensity { get; set; } public int RoomSize { get; set; } - public string MonsterType { get; set; } = string.Empty; + [StringLength(50)] public required string MonsterType { get; set; } public int TrapPercent { get; set; } public bool DeadEnd { get; set; } public bool Corridor { get; set; } public int RoamingPercent { get; set; } - public int UserId { get; set; } public User? User { get; set; } - public IEnumerable Dungeons { get; } = new List(); + public List Dungeons { get; set; } = []; } \ No newline at end of file diff --git a/src/Open5ETools.Core/Domain/DM/Option.cs b/src/Open5ETools.Core/Domain/DM/Option.cs index 1a22a23..9ad8dd1 100644 --- a/src/Open5ETools.Core/Domain/DM/Option.cs +++ b/src/Open5ETools.Core/Domain/DM/Option.cs @@ -1,10 +1,11 @@ -using Open5ETools.Core.Common.Enums.DM; +using System.ComponentModel.DataAnnotations; +using Open5ETools.Core.Common.Enums.DM; namespace Open5ETools.Core.Domain.DM; public class Option : BaseEntity { public OptionKey Key { get; set; } - public string Name { get; set; } = string.Empty; - public string Value { get; set; } = string.Empty; + [StringLength(short.MaxValue)] public required string Name { get; set; } + [StringLength(short.MaxValue)] public required string Value { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Core/Domain/DM/Treasure.cs b/src/Open5ETools.Core/Domain/DM/Treasure.cs index e9ce132..d27c61d 100644 --- a/src/Open5ETools.Core/Domain/DM/Treasure.cs +++ b/src/Open5ETools.Core/Domain/DM/Treasure.cs @@ -4,5 +4,5 @@ namespace Open5ETools.Core.Domain.DM; public class Treasure : AuditableEntity { - public TreasureDescription TreasureDescription { get; set; } = null!; + public required TreasureDescription TreasureDescription { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Core/Domain/EG/Monster.cs b/src/Open5ETools.Core/Domain/EG/Monster.cs index daec541..525745c 100644 --- a/src/Open5ETools.Core/Domain/EG/Monster.cs +++ b/src/Open5ETools.Core/Domain/EG/Monster.cs @@ -2,5 +2,5 @@ namespace Open5ETools.Core.Domain.EG; public class Monster : AuditableEntity { - public Common.Models.Json.Monster JsonMonster { get; set; } = new(); -} + public required Common.Models.Json.Monster JsonMonster { get; set; } +} \ No newline at end of file diff --git a/src/Open5ETools.Core/Domain/SM/Spell.cs b/src/Open5ETools.Core/Domain/SM/Spell.cs index 2eee74d..3a45405 100644 --- a/src/Open5ETools.Core/Domain/SM/Spell.cs +++ b/src/Open5ETools.Core/Domain/SM/Spell.cs @@ -1,44 +1,27 @@ +using System.ComponentModel.DataAnnotations; using Open5ETools.Core.Common.Enums.SM; namespace Open5ETools.Core.Domain.SM; public class Spell : AuditableEntity { - public string Name { get; set; } = string.Empty; - - public string Desc { get; set; } = string.Empty; - - public string? HigherLevel { get; set; } - - public string Page { get; set; } = string.Empty; - - public string Range { get; set; } = string.Empty; - - public string Components { get; set; } = string.Empty; - - public string? Material { get; set; } - + [StringLength(short.MaxValue)] public required string Name { get; set; } + [StringLength(short.MaxValue)] public required string Desc { get; set; } + [StringLength(short.MaxValue)] public required string Page { get; set; } + [StringLength(short.MaxValue)] public required string Range { get; set; } + [StringLength(short.MaxValue)] public required string Components { get; set; } + [StringLength(short.MaxValue)] public required string CastingTime { get; set; } + [StringLength(short.MaxValue)] public required string Level { get; set; } + [StringLength(short.MaxValue)] public required string Class { get; set; } + public School School { get; set; } public bool Ritual { get; set; } - - public string? Duration { get; set; } - public bool Concentration { get; set; } - - public string CastingTime { get; set; } = string.Empty; - - public string Level { get; set; } = string.Empty; - - public School School { get; set; } - - public string Class { get; set; } = string.Empty; - - public string? Archetype { get; set; } - - public string? Circles { get; set; } - - public string? Domains { get; set; } - - public string? Oaths { get; set; } - - public string? Patrons { get; set; } -} + [StringLength(short.MaxValue)] public string? HigherLevel { get; set; } + [StringLength(short.MaxValue)] public string? Material { get; set; } + [StringLength(short.MaxValue)] public string? Duration { get; set; } + [StringLength(short.MaxValue)] public string? Archetype { get; set; } + [StringLength(short.MaxValue)] public string? Circles { get; set; } + [StringLength(short.MaxValue)] public string? Domains { get; set; } + [StringLength(short.MaxValue)] public string? Oaths { get; set; } + [StringLength(short.MaxValue)] public string? Patrons { get; set; } +} \ No newline at end of file diff --git a/src/Open5ETools.Core/Domain/User.cs b/src/Open5ETools.Core/Domain/User.cs index 65414e3..407feac 100644 --- a/src/Open5ETools.Core/Domain/User.cs +++ b/src/Open5ETools.Core/Domain/User.cs @@ -1,3 +1,4 @@ +using System.ComponentModel.DataAnnotations; using Open5ETools.Core.Common.Enums; using Open5ETools.Core.Common.Interfaces; @@ -5,11 +6,11 @@ namespace Open5ETools.Core.Domain; public class User : AuditableEntity, ISoftDelete { - public string Username { get; set; } = string.Empty; - public string FirstName { get; set; } = string.Empty; - public string LastName { get; set; } = string.Empty; - public string Email { get; set; } = string.Empty; - public string Password { get; set; } = string.Empty; + [StringLength(short.MaxValue)] public required string Username { get; set; } + [StringLength(short.MaxValue)] public required string FirstName { get; set; } + [StringLength(short.MaxValue)] public required string LastName { get; set; } + [StringLength(short.MaxValue)] public required string Email { get; set; } + [StringLength(short.MaxValue)] public required string Password { get; set; } public Role Role { get; set; } public bool IsDeleted { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Core/Open5ETools.Core.csproj b/src/Open5ETools.Core/Open5ETools.Core.csproj index 68ba417..1e9afb1 100644 --- a/src/Open5ETools.Core/Open5ETools.Core.csproj +++ b/src/Open5ETools.Core/Open5ETools.Core.csproj @@ -1,7 +1,5 @@  - - diff --git a/src/Open5ETools.Core/Services/AuthService.cs b/src/Open5ETools.Core/Services/AuthService.cs index 3060b31..ffa5ed7 100644 --- a/src/Open5ETools.Core/Services/AuthService.cs +++ b/src/Open5ETools.Core/Services/AuthService.cs @@ -1,32 +1,35 @@ -using MapsterMapper; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Open5ETools.Core.Common.Helpers; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Common.Interfaces.Services; +using Open5ETools.Core.Common.Mappers; using Open5ETools.Core.Common.Models.Services; namespace Open5ETools.Core.Services; -public class AuthService(IMapper mapper, IAppDbContext context, ILogger logger) : IAuthService +public class AuthService(IAppDbContext context, ILogger logger) : IAuthService { private readonly IAppDbContext _context = context; - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; - public async Task LoginAsync(UserModel model, CancellationToken cancellationToken = default) + public async Task LoginAsync( + string userName, + string password, + CancellationToken cancellationToken + ) { try { var user = await _context.Users .AsNoTracking() .Where(u => u.IsDeleted == false) - .FirstOrDefaultAsync(u => u.Username == model.Username, cancellationToken); + .FirstOrDefaultAsync(u => u.Username == userName, cancellationToken); if (user is null) return null; - return PasswordHelper.CheckPassword(user.Password, model.Password) ? _mapper.Map(user) : null; + return PasswordHelper.CheckPassword(user.Password, password) ? user.ToModel() : null; } catch (Exception ex) { diff --git a/src/Open5ETools.Core/Services/DM/DungeonService.cs b/src/Open5ETools.Core/Services/DM/DungeonService.cs index 21adb72..a62c1d6 100644 --- a/src/Open5ETools.Core/Services/DM/DungeonService.cs +++ b/src/Open5ETools.Core/Services/DM/DungeonService.cs @@ -1,19 +1,17 @@ using System.Text.Json; -using MapsterMapper; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Open5ETools.Core.Common.Exceptions; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Common.Interfaces.Services.DM; using Open5ETools.Core.Common.Interfaces.Services.DM.Generator; +using Open5ETools.Core.Common.Mappers; using Open5ETools.Core.Common.Models.DM.Services; -using Open5ETools.Core.Domain.DM; using Open5ETools.Resources; namespace Open5ETools.Core.Services.DM; public class DungeonService( - IMapper mapper, IAppDbContext context, IDungeon dungeon, IDungeonNoCorridor dungeonNcDungeon, @@ -22,7 +20,6 @@ public class DungeonService( private readonly IAppDbContext _context = context; private readonly IDungeon _dungeon = dungeon; private readonly IDungeonNoCorridor _dungeonNcDungeon = dungeonNcDungeon; - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; public async Task CreateDungeonOptionAsync(DungeonOptionModel dungeonOption, @@ -31,7 +28,7 @@ public async Task CreateDungeonOptionAsync(DungeonOptionModel dungeonOption try { ValidateModel(dungeonOption); - var option = _mapper.Map(dungeonOption); + var option = dungeonOption.ToEntity(); _context.DungeonOptions.Add(option); await _context.SaveChangesAsync(cancellationToken); return option.Id; @@ -58,7 +55,7 @@ public async Task AddDungeonAsync(DungeonModel savedDungeon, CancellationTo { try { - var dungeonEntity = _mapper.Map(savedDungeon); + var dungeonEntity = savedDungeon.ToEntity(); _context.Dungeons.Add(dungeonEntity); await _context.SaveChangesAsync(cancellationToken); return dungeonEntity.Id; @@ -98,7 +95,7 @@ public async Task CreateOrUpdateDungeonAsync(DungeonOptionModel op cancellationToken); } - optionModel.Id = existingDungeonOption.Id; + optionModel = optionModel with { Id = existingDungeonOption.Id }; return await AddDungeonToExistingOptionAsync(optionModel, level, cancellationToken); } catch (Exception ex) @@ -112,8 +109,7 @@ private async Task UpdateExistingDungeonAsync(DungeonOptionModel o DungeonOptionModel existingDungeonOption, DungeonModel oldDungeon, CancellationToken cancellationToken) { var dungeonModel = await GenerateDungeonAsync(optionModel, existingDungeonOption.Id, cancellationToken); - dungeonModel.Id = oldDungeon.Id; - dungeonModel.Level = oldDungeon.Level; + dungeonModel = dungeonModel with { Id = oldDungeon.Id, Level = oldDungeon.Level }; await UpdateDungeonAsync(dungeonModel, cancellationToken); return dungeonModel; } @@ -123,9 +119,9 @@ private async Task CreateOptionAndAddDungeonToItAsync(DungeonOptio { var dungeonOptionId = await CreateDungeonOptionAsync(optionModel, cancellationToken); var dungeonModel = await GenerateDungeonAsync(optionModel, dungeonOptionId, cancellationToken); - dungeonModel.Level = 1; + dungeonModel = dungeonModel with { Level = 1 }; var id = await AddDungeonAsync(dungeonModel, cancellationToken); - dungeonModel.Id = id; + dungeonModel = dungeonModel with { Id = id }; return dungeonModel; } @@ -136,15 +132,15 @@ private async Task AddDungeonToExistingOptionAsync(DungeonOptionMo (await ListUserDungeonsByNameAsync(optionModel.DungeonName, optionModel.UserId, cancellationToken)) .ToList(); var dungeonModel = await GenerateDungeonAsync(optionModel, optionModel.Id, cancellationToken); - dungeonModel.Level = level; + dungeonModel = dungeonModel with { Level = level }; if (existingDungeons.Exists(d => d.Level == level)) { - dungeonModel.Id = existingDungeons.First(dm => dm.Level == level).Id; + dungeonModel = dungeonModel with { Id = existingDungeons.First(dm => dm.Level == level).Id }; await UpdateDungeonAsync(dungeonModel, cancellationToken); } else { - dungeonModel.Id = await AddDungeonAsync(dungeonModel, cancellationToken); + dungeonModel = dungeonModel with { Id = await AddDungeonAsync(dungeonModel, cancellationToken) }; } return dungeonModel; @@ -154,7 +150,7 @@ private async Task GenerateDungeonAsync(DungeonOptionModel optionM CancellationToken cancellationToken) { var dungeonModel = await GenerateDungeonAsync(optionModel, cancellationToken); - dungeonModel.DungeonOptionId = optionId; + dungeonModel = dungeonModel with { DungeonOptionId = optionId }; return dungeonModel; } @@ -185,7 +181,7 @@ public async Task GetAllDungeonOptionsAsync(CancellationTo .OrderBy(d => d.Created) .ToArrayAsync(cancellationToken); - return [.. options.Select(_mapper.Map)]; + return [.. options.Select(d => d.ToModel())]; } catch (Exception ex) { @@ -206,7 +202,7 @@ public async Task GetAllDungeonOptionsForUserAsync(int use .OrderBy(d => d.Created) .ToArrayAsync(cancellationToken); - return [.. options.Select(_mapper.Map)]; + return [.. options.Select(d => d.ToModel())]; } catch (Exception ex) { @@ -225,7 +221,7 @@ public async Task GetAllDungeonOptionsForUserAsync(int use .AsNoTracking() .Where(d => d.DungeonName.Equals(dungeonName) && d.UserId == userId) .FirstOrDefaultAsync(cancellationToken); - return dungeonOption is not null ? _mapper.Map(dungeonOption) : null; + return dungeonOption?.ToModel(); } catch (Exception ex) { @@ -291,7 +287,7 @@ private async Task DeleteDungeonOptionIfNeededAsync(int dungeonOptionId, Cancell var entity = await _context.DungeonOptions .Include(d => d.Dungeons) .FirstOrDefaultAsync(d => d.Id == dungeonOptionId, cancellationToken); - if (entity is not null && !entity.Dungeons.Any()) + if (entity is not null && entity.Dungeons.Count == 0) { _context.DungeonOptions.Remove(entity); await _context.SaveChangesAsync(cancellationToken); @@ -309,7 +305,7 @@ public async Task ListUserDungeonsAsync(int userId, Cancellation .OrderBy(d => d.Created) .SelectMany(d => d.Dungeons) .ToArrayAsync(cancellationToken); - return [.. result.Select(_mapper.Map)]; + return [.. result.Select(d => d.ToModel())]; } catch (Exception ex) { @@ -330,7 +326,7 @@ public async Task ListUserDungeonsByNameAsync(string dungeonName .OrderBy(d => d.Created) .SelectMany(d => d.Dungeons) .ToArrayAsync(cancellationToken); - return [.. result.Select(_mapper.Map)]; + return [.. result.Select(d => d.ToModel())]; } catch (Exception ex) { @@ -343,10 +339,10 @@ public async Task GetDungeonAsync(int id, CancellationToken cancel { try { - return _mapper.Map(await _context.Dungeons - .AsNoTracking() - .FirstOrDefaultAsync(d => d.Id == id, cancellationToken) ?? - throw new ServiceException(Error.NotFound)); + return (await _context.Dungeons + .AsNoTracking() + .FirstOrDefaultAsync(d => d.Id == id, cancellationToken) ?? + throw new ServiceException(Error.NotFound)).ToModel(); } catch (Exception ex) { @@ -359,11 +355,10 @@ public async Task UpdateDungeonAsync(DungeonModel model, CancellationToken cance { try { - var entity = await _context.Dungeons - .FirstOrDefaultAsync(d => d.Id == model.Id, cancellationToken); + var entity = await _context.Dungeons.FirstOrDefaultAsync(d => d.Id == model.Id, cancellationToken); if (entity is not null) { - _mapper.Map(model, entity); + DungeonMapper.Map(entity, model); await _context.SaveChangesAsync(cancellationToken); } } @@ -378,9 +373,9 @@ public async Task GetDungeonOptionAsync(int id, Cancellation { try { - return _mapper.Map( + return ( await _context.DungeonOptions.FirstOrDefaultAsync(d => d.Id == id, cancellationToken) ?? - throw new ServiceException(Error.NotFound)); + throw new ServiceException(Error.NotFound)).ToModel(); } catch (Exception ex) { @@ -393,8 +388,8 @@ public async Task RenameDungeonAsync(int optionId, int userId, string newName, C { try { - var entity = await _context.DungeonOptions.FirstOrDefaultAsync(d => d.Id == optionId && d.UserId == userId, - cancellationToken); + var entity = await _context.DungeonOptions + .FirstOrDefaultAsync(d => d.Id == optionId && d.UserId == userId, cancellationToken); if (entity is not null) { entity.DungeonName = newName; @@ -412,11 +407,11 @@ public async Task ExportToJsonAsync(int dungeonId, CancellationToken can { try { - var dungeon = _mapper.Map(await _context.Dungeons - .AsNoTracking() - .FirstOrDefaultAsync(d => d.Id == dungeonId, - cancellationToken) ?? - throw new ServiceException(Error.NotFound)); + var dungeon = (await _context.Dungeons + .AsNoTracking() + .FirstOrDefaultAsync(d => d.Id == dungeonId, + cancellationToken) ?? + throw new ServiceException(Error.NotFound)).ToModel(); return JsonSerializer.Serialize(dungeon); } diff --git a/src/Open5ETools.Core/Services/DM/Generator/Dungeon.cs b/src/Open5ETools.Core/Services/DM/Generator/Dungeon.cs index 6db3d37..b448317 100644 --- a/src/Open5ETools.Core/Services/DM/Generator/Dungeon.cs +++ b/src/Open5ETools.Core/Services/DM/Generator/Dungeon.cs @@ -40,13 +40,20 @@ public virtual DungeonModel Generate(DungeonOptionModel model) AddCorridorItem(_trapCount, Item.Trap); AddCorridorItem(_roamingCount, Item.RoamingMonster); return new DungeonModel - { - DungeonTiles = JsonSerializer.Serialize(DungeonTiles), - RoomDescription = JsonSerializer.Serialize(RoomDescription), - TrapDescription = JsonSerializer.Serialize(TrapDescription), - RoamingMonsterDescription = JsonSerializer.Serialize(RoamingMonsterDescription), - DungeonOptionId = model.Id - }; + ( + JsonSerializer.Serialize(DungeonTiles), + JsonSerializer.Serialize(RoomDescription), + JsonSerializer.Serialize(TrapDescription), + JsonSerializer.Serialize(RoamingMonsterDescription), + model.Id, + 0, + 0, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); } public void AddCorridorItem(int inCount, Item item) @@ -116,10 +123,12 @@ private List GenerateDeadEnds() { croppedDungeonTiles[i] = new DungeonTile[DungeonTiles.Length - 4]; } + for (var i = 2; i < DungeonTiles.Length - 2; i++) { Array.Copy(DungeonTiles[i], 2, croppedDungeonTiles[i - 2], 0, DungeonTiles[i].Length - 4); } + var dungeonList = croppedDungeonTiles.SelectMany(T => T).ToList(); dungeonList.RemoveAll(Rooms.Contains); dungeonList.RemoveAll(Doors.Contains); @@ -134,9 +143,10 @@ private List GenerateDeadEnds() deadEnds.Add(DungeonTiles[tile.I][tile.J]); deadEndsCount++; } + maxAttempt--; - } - while (count != deadEndsCount && maxAttempt > 0); + } while (count != deadEndsCount && maxAttempt > 0); + return deadEnds; } @@ -150,6 +160,7 @@ private bool CheckTileForDeadEnd(int x, int y) return false; } } + return true; } @@ -172,6 +183,7 @@ public void GenerateCorridors() DungeonTiles[i][j].F = 9999; } } + AddToClosedList(closedList, start); // add start point to closed list AddToOpen(start, openList, closedList, end); // add the nearby nodes to openList while (_result.Count == 0 && openList.Count != 0) @@ -181,6 +193,7 @@ public void GenerateCorridors() RemoveFromOpen(openList, start); // remove from open list this node AddToOpen(start, openList, closedList, end); // add open list the nearby nodes } + SetPath(); // modify tiles Texture with the path } } @@ -200,7 +213,8 @@ internal static void RemoveFromOpen(List openList, DungeonTile node openList.Remove(node); } - private void AddToOpen(DungeonTile node, List openList, ICollection closedList, DungeonTile end) + private void AddToOpen(DungeonTile node, List openList, ICollection closedList, + DungeonTile end) { AddToOpenList(node, node.I, node.J - 1, openList, closedList, end); // left AddToOpenList(node, node.I - 1, node.J, openList, closedList, end); // top @@ -221,12 +235,14 @@ private static void CalcGValue(List openList) openList.ForEach(tile => tile.G = tile.Parent?.G ?? 0 + Movement); } - private void AddToOpenList(DungeonTile node, int x, int y, List openList, ICollection closedList, DungeonTile end) + private void AddToOpenList(DungeonTile node, int x, int y, List openList, + ICollection closedList, DungeonTile end) { if (CheckEnd(node, x, y, end)) return; CheckG(node, x, y, openList); // check if it needs reparenting - if (!CheckTileForOpenList(x, y) || closedList.Contains(DungeonTiles[x][y]) || openList.Contains(DungeonTiles[x][y])) + if (!CheckTileForOpenList(x, y) || closedList.Contains(DungeonTiles[x][y]) || + openList.Contains(DungeonTiles[x][y])) return; // not in openlist/closedlist SetParent(node, x, y); openList.Add(DungeonTiles[x][y]); @@ -239,7 +255,8 @@ private void SetParent(DungeonTile node, int x, int y) protected virtual bool CheckTileForOpenList(int x, int y) { - return DungeonTiles[x][y].H != 0 && DungeonTiles[x][y].Texture != Texture.Room && DungeonTiles[x][y].Texture != Texture.RoomEdge; // check its not edge/room/room_edge + return DungeonTiles[x][y].H != 0 && DungeonTiles[x][y].Texture != Texture.Room && + DungeonTiles[x][y].Texture != Texture.RoomEdge; // check its not edge/room/room_edge } private void CheckG(DungeonTile node, int x, int y, List openList) @@ -283,8 +300,8 @@ public virtual void AddEntryPoint() x = DungeonHelper.GetRandomInt(1, DungeonTiles.Length - 1); y = DungeonHelper.GetRandomInt(1, DungeonTiles.Length - 1); entryIsOk = DungeonTiles[x][y].Texture == Texture.Marble; - } - while (!entryIsOk); + } while (!entryIsOk); + DungeonTiles[x][y].Texture = Texture.Entry; Doors.Add(DungeonTiles[x][y]); } @@ -309,6 +326,7 @@ protected virtual void FillRoom(int x, int y, int right, int down) DungeonTiles[x + i - 1][y + j - 1].Texture = Texture.RoomEdge; } } + for (var i = 0; i < down; i++) // fill room texture { for (var j = 0; j < right; j++) @@ -319,11 +337,13 @@ protected virtual void FillRoom(int x, int y, int right, int down) DungeonTiles[x + i][y + j].Index = RoomDescription.Count; } } + var currentSize = Doors.Count; for (var d = 0; d < doorCount; d++) { AddDoor(x, y, down, right); } + var newSize = Doors.Count; var currentDoors = Doors.GetRange(currentSize, newSize - currentSize); _dungeonHelper.AddRoomDescription(DungeonTiles, x, y, RoomDescription, currentDoors); @@ -337,8 +357,7 @@ internal void AddDoor(int x, int y, int down, int right) var doorX = DungeonHelper.GetRandomInt(x, x + down); var doorY = DungeonHelper.GetRandomInt(y, y + right); doorIsOk = CheckDoor(doorX, doorY); - } - while (!doorIsOk); + } while (!doorIsOk); } protected virtual bool CheckDoor(int x, int y) @@ -347,10 +366,12 @@ protected virtual bool CheckDoor(int x, int y) { for (var j = y - 1; j < y + 2; j++) { - if (DungeonTiles[i][j].Texture is Texture.Door or Texture.DoorLocked or Texture.DoorTrapped) // check nearby doors + if (DungeonTiles[i][j].Texture is Texture.Door or Texture.DoorLocked + or Texture.DoorTrapped) // check nearby doors return false; } } + return CheckEnvironment(x, y); } @@ -361,16 +382,19 @@ internal bool CheckEnvironment(int x, int y) SetDoor(x, y - 1); return true; } + if (DungeonTiles[x][y + 1].Texture == Texture.RoomEdge) // right { SetDoor(x, y + 1); return true; } + if (DungeonTiles[x + 1][y].Texture == Texture.RoomEdge) // bottom { SetDoor(x + 1, y); return true; } + if (DungeonTiles[x - 1][y].Texture == Texture.RoomEdge) // top { SetDoor(x - 1, y); @@ -413,10 +437,11 @@ private int[] SetTilesForRoom() y = DungeonHelper.GetRandomInt(3, max); right = DungeonHelper.GetRandomInt(2, RoomSize + 1); down = DungeonHelper.GetRandomInt(2, RoomSize + 1); - roomIsOk = CheckTileGoodForRoom(x - 2, y - 2, right + 2, down + 2); // -2/+2 because i want min 3 tiles between rooms + roomIsOk = CheckTileGoodForRoom(x - 2, y - 2, right + 2, + down + 2); // -2/+2 because i want min 3 tiles between rooms failSafeCount--; - } - while (!roomIsOk && failSafeCount > 0); + } while (!roomIsOk && failSafeCount > 0); + return failSafeCount > 0 ? [x, y, right, down] : [0, 0, 0, 0]; // it can never be 0 if its a good coordinate } @@ -432,6 +457,7 @@ private bool CheckTileGoodForRoom(int x, int y, int right, int down) return false; } } + return true; } diff --git a/src/Open5ETools.Core/Services/DM/Generator/DungeonNoCorridor.cs b/src/Open5ETools.Core/Services/DM/Generator/DungeonNoCorridor.cs index a3f2fff..af201ef 100644 --- a/src/Open5ETools.Core/Services/DM/Generator/DungeonNoCorridor.cs +++ b/src/Open5ETools.Core/Services/DM/Generator/DungeonNoCorridor.cs @@ -23,13 +23,20 @@ public override DungeonModel Generate(DungeonOptionModel model) AddEntryPoint(); AddDescription(); return new DungeonModel - { - DungeonTiles = JsonSerializer.Serialize(DungeonTiles), - RoomDescription = JsonSerializer.Serialize(RoomDescription), - DungeonOptionId = model.Id, - TrapDescription = Constants.Empty, - RoamingMonsterDescription = Constants.Empty - }; + ( + JsonSerializer.Serialize(DungeonTiles), + JsonSerializer.Serialize(RoomDescription), + Constants.Empty, + Constants.Empty, + model.Id, + 0, + 0, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); } public override void Init(DungeonOptionModel optionModel) diff --git a/src/Open5ETools.Core/Services/DM/OptionService.cs b/src/Open5ETools.Core/Services/DM/OptionService.cs index c0775ed..a6bce29 100644 --- a/src/Open5ETools.Core/Services/DM/OptionService.cs +++ b/src/Open5ETools.Core/Services/DM/OptionService.cs @@ -1,23 +1,22 @@ -using MapsterMapper; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Open5ETools.Core.Common.Enums.DM; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Common.Interfaces.Services.DM; +using Open5ETools.Core.Common.Mappers; using Open5ETools.Core.Common.Models.DM.Services; namespace Open5ETools.Core.Services.DM; public class OptionService( - IMapper mapper, IAppDbContext context, IMemoryCache memoryCache, - ILogger logger) : IOptionService + ILogger logger +) : IOptionService { private readonly IAppDbContext _context = context; private readonly IMemoryCache _memoryCache = memoryCache; - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; public async Task ListOptionsAsync(OptionKey? filter = null, @@ -32,7 +31,7 @@ public async Task ListOptionsAsync(OptionKey? filter = null, var options = await _context.Options.AsNoTracking().ToArrayAsync(cancellationToken); - cacheEntry = [.. options.Select(_mapper.Map)]; + cacheEntry = [.. options.Select(o => o.ToModel())]; var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromMinutes(10)); diff --git a/src/Open5ETools.Core/Services/EG/EncounterService.cs b/src/Open5ETools.Core/Services/EG/EncounterService.cs index 2f2f373..e50f166 100644 --- a/src/Open5ETools.Core/Services/EG/EncounterService.cs +++ b/src/Open5ETools.Core/Services/EG/EncounterService.cs @@ -1,5 +1,4 @@ -using MapsterMapper; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Open5ETools.Core.Common; using Open5ETools.Core.Common.Enums.EG; @@ -8,28 +7,27 @@ using Open5ETools.Core.Common.Helpers; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Common.Interfaces.Services.EG; +using Open5ETools.Core.Common.Mappers; using Open5ETools.Core.Common.Models.EG; -using Open5ETools.Core.Domain.EG; using Open5ETools.Resources; using Enum = System.Enum; +using Monster = Open5ETools.Core.Domain.EG.Monster; namespace Open5ETools.Core.Services.EG; public class EncounterService( - IMapper mapper, IAppDbContext context, ILogger logger ) : IEncounterService { - private readonly IMapper _mapper = mapper; private readonly IAppDbContext _context = context; private readonly ILogger _logger = logger; private List _monsters = []; private int _partyLevel; private int _partySize; - private ICollection> _xpList = []; + private KeyValuePair[] _xpList = []; - public async Task>> GetEnumListAsync() where T : struct + public async Task[]> GetEnumListAsync() where T : struct { if (!typeof(T).IsEnum) throw new InvalidOperationException("Type parameter must be Enum."); @@ -38,7 +36,7 @@ public async Task>> GetEnumListAsync() (from object e in Enum.GetValues(typeof(T)) select new KeyValuePair(((Enum)e) .GetName(Resources.Enum.ResourceManager), (int)e)) - .ToList()); + .ToArray()); } public async Task GenerateAsync(EncounterOption option) @@ -59,13 +57,13 @@ public async Task GenerateAsync(EncounterOption option) var sumXp = CalcSumXp((int)Difficulty.Deadly); var monsterXps = new SortedSet(); - if (option.MonsterTypes.Any()) + if (option.MonsterTypes.Length != 0) { var selectedMonsters = option.MonsterTypes.Select(m => m.ToString().ToLower()); _monsters = [.. _monsters.Where(m => selectedMonsters.Any(m.JsonMonster.Type.ToLower().Equals))]; } - if (option.Sizes.Any()) + if (option.Sizes.Length != 0) { var selectedSizes = option.Sizes.Select(s => s.ToString().ToLower()); _monsters = [.. _monsters.Where(m => selectedSizes.Any(m.JsonMonster.Size.ToLower().Equals))]; @@ -83,17 +81,17 @@ public async Task GenerateAsync(EncounterOption option) CheckPossible(sumXp, monsterXps); - var result = new EncounterModel(); + var encounterDetails = new List(); var maxTryNumber = 5000; await Task.Run(() => { - while (result.Monsters.Count < option.Count && maxTryNumber > 0) + while (encounterDetails.Count < option.Count && maxTryNumber > 0) { try { var monster = GetMonster(option.Difficulty); if (monster is not null) - result.Monsters.Add(monster); + encounterDetails.Add(monster); maxTryNumber--; } catch (ServiceException) @@ -103,9 +101,7 @@ await Task.Run(() => } }); - result.SumXp = result.Monsters.Sum(mm => mm.JsonMonsterModel.Xp); - - return result; + return new EncounterModel([..encounterDetails]); } catch (Exception ex) { @@ -134,7 +130,7 @@ private static void ValidateOption(EncounterOption? option) throw new ServiceAggregateException(exceptions); } - private static void CheckPossible(int sumXp, IReadOnlyCollection monsterXps) + private static void CheckPossible(int sumXp, SortedSet monsterXps) { if (monsterXps.Count != 0 && sumXp > monsterXps.First()) return; @@ -145,19 +141,18 @@ private static void CheckPossible(int sumXp, IReadOnlyCollection monsterXps { var monsterCount = _monsters.Count; var monster = 0; - var indexes = new List(Enumerable.Range(0, Constants.Multipliers.GetLength(0))); while (monster < monsterCount) { var currentMonster = _monsters.ElementAt(DungeonHelper.GetRandomInt(0, _monsters.Count)); _monsters.Remove(currentMonster); var monsterXp = DungeonHelper.GetMonsterXp(currentMonster.JsonMonster); - indexes.Shuffle(); + Constants.MultipliersIndexes.Shuffle(); if (difficulty.HasValue) { var difficultyXp = _xpList.First(l => l.Key == difficulty.Value).Value; - foreach (var i in indexes) + foreach (var i in Constants.MultipliersIndexes) { var count = (int)Constants.Multipliers[i, 0]; var allXp = monsterXp * count * Constants.Multipliers[i, 1]; @@ -165,18 +160,18 @@ private static void CheckPossible(int sumXp, IReadOnlyCollection monsterXps _xpList.OrderByDescending(l => l.Value).First(l => allXp >= l.Value).Key != difficulty) continue; - return GetEncounterDetail(difficulty.Value, currentMonster, (int)allXp, count); + return currentMonster.ToModel(difficulty.Value, (int)allXp, count); } } else { - foreach (var i in indexes) + foreach (var i in Constants.MultipliersIndexes) { var count = (int)Constants.Multipliers[i, 0]; var allXp = monsterXp * count * Constants.Multipliers[i, 1]; var difficulties = _xpList.Where(xp => allXp <= xp.Value).Select(xp => xp.Key).AsQueryable(); if (difficulties.Any()) - return GetEncounterDetail(difficulties.First(), currentMonster, (int)allXp, count); + return currentMonster.ToModel(difficulties.First(), (int)allXp, count); } } @@ -186,21 +181,6 @@ private static void CheckPossible(int sumXp, IReadOnlyCollection monsterXps return null; } - private MonsterModel GetEncounterDetail(Difficulty difficulty, Monster currentMonster, int allXp, int count) - { - var monsterModel = _mapper.Map(currentMonster); - monsterModel.JsonMonsterModel.Xp = allXp; - monsterModel.JsonMonsterModel.Count = count; - monsterModel.JsonMonsterModel.Difficulty = difficulty.GetName(Resources.Enum.ResourceManager); - monsterModel.JsonMonsterModel.Size = - Enum.Parse(currentMonster.JsonMonster.Size).GetName(Resources.Enum.ResourceManager); - - if (Enum.TryParse(monsterModel.JsonMonsterModel.Type, out MonsterType type)) - monsterModel.JsonMonsterModel.Type = type.GetName(Resources.Enum.ResourceManager); - - return monsterModel; - } - public async Task GetMonsterByIdAsync(int id) { var monster = await _context.Monsters @@ -208,6 +188,6 @@ public async Task GetMonsterByIdAsync(int id) .FirstOrDefaultAsync(m => m.Id == id) ?? throw new ServiceException(Error.NotFound); - return _mapper.Map(monster); + return monster.ToModel(); } } \ No newline at end of file diff --git a/src/Open5ETools.Core/Services/SM/SpellService.cs b/src/Open5ETools.Core/Services/SM/SpellService.cs index 95414bb..9f26406 100644 --- a/src/Open5ETools.Core/Services/SM/SpellService.cs +++ b/src/Open5ETools.Core/Services/SM/SpellService.cs @@ -1,21 +1,19 @@ -using MapsterMapper; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Open5ETools.Core.Common.Exceptions; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Common.Interfaces.Services.SM; +using Open5ETools.Core.Common.Mappers; using Open5ETools.Core.Common.Models.SM; using Open5ETools.Resources; namespace Open5ETools.Core.Services.SM; public class SpellService( - IMapper mapper, IAppDbContext context, ILogger logger ) : ISpellService { - private readonly IMapper _mapper = mapper; private readonly IAppDbContext _context = context; private readonly ILogger _logger = logger; @@ -28,7 +26,7 @@ public async Task GetAsync(int id, CancellationToken cancellationTok .FirstOrDefaultAsync(u => u.Id == id, cancellationToken) ?? throw new ServiceException(Error.NotFound); - return _mapper.Map(spell); + return spell.ToModel(); } catch (Exception ex) { @@ -37,8 +35,7 @@ public async Task GetAsync(int id, CancellationToken cancellationTok } } - public async Task> ListAsync(string? search = null, - CancellationToken cancellationToken = default) + public async Task ListAsync(string? search = null, CancellationToken cancellationToken = default) { try { @@ -53,8 +50,8 @@ public async Task> ListAsync(string? search = null, || EF.Functions.Like(s.Components, $"%{search}%") ); - var items = await query.ToListAsync(cancellationToken); - return items.Select(_mapper.Map); + var items = await query.ToArrayAsync(cancellationToken); + return [.. items.Select(s => s.ToModel())]; } catch (Exception ex) { diff --git a/src/Open5ETools.Core/Services/UserService.cs b/src/Open5ETools.Core/Services/UserService.cs index 4da9e3c..066fca2 100644 --- a/src/Open5ETools.Core/Services/UserService.cs +++ b/src/Open5ETools.Core/Services/UserService.cs @@ -1,22 +1,20 @@ -using MapsterMapper; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Open5ETools.Core.Common.Enums; using Open5ETools.Core.Common.Exceptions; using Open5ETools.Core.Common.Helpers; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Common.Interfaces.Services; +using Open5ETools.Core.Common.Mappers; using Open5ETools.Core.Common.Models.Services; using Open5ETools.Resources; using Enum = System.Enum; -using User = Open5ETools.Core.Domain.User; namespace Open5ETools.Core.Services; -public class UserService(IMapper mapper, IAppDbContext context, ILogger logger) : IUserService +public class UserService(IAppDbContext context, ILogger logger) : IUserService { private readonly IAppDbContext _context = context; - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; public async Task CreateAsync(UserModel model, CancellationToken cancellationToken = default) @@ -25,8 +23,8 @@ public async Task CreateAsync(UserModel model, CancellationToken cancellati await CheckUserExistAsync(model, cancellationToken); try { - model.Password = PasswordHelper.EncryptPassword(model.Password); - var user = _mapper.Map(model); + model = model with { Password = PasswordHelper.EncryptPassword(model.Password) }; + var user = model.ToEntity(); _context.Users.Add(user); await _context.SaveChangesAsync(cancellationToken); return user.Id; @@ -99,7 +97,7 @@ public async Task GetAsync(int id, CancellationToken cancellationToke .FirstOrDefaultAsync(u => u.Id == id, cancellationToken) ?? throw new ServiceException(Error.NotFound); - return _mapper.Map(user); + return user.ToModel(); } catch (Exception ex) { @@ -120,7 +118,7 @@ public async Task ListAsync(bool? deleted = false, CancellationToke return [ .. (await query.ToListAsync(cancellationToken)) - .Select(_mapper.Map) + .Select(u => u.ToModel()) .OrderBy(um => um.Username) ]; } @@ -136,14 +134,11 @@ public async Task RestoreAsync(int id, CancellationToken cancellationToken try { var user = await _context.Users.FirstOrDefaultAsync(u => u.Id == id && u.IsDeleted, cancellationToken); - if (user is not null) - { - user.IsDeleted = false; - await _context.SaveChangesAsync(cancellationToken); - return true; - } - - return false; + if (user is null) + return false; + user.IsDeleted = false; + await _context.SaveChangesAsync(cancellationToken); + return true; } catch (Exception ex) { diff --git a/src/Open5ETools.Infrastructure/Data/AppDbContext.cs b/src/Open5ETools.Infrastructure/Data/AppDbContext.cs index 5f7c1ec..6ab5790 100644 --- a/src/Open5ETools.Infrastructure/Data/AppDbContext.cs +++ b/src/Open5ETools.Infrastructure/Data/AppDbContext.cs @@ -1,3 +1,4 @@ +using System.Text.Json; using Microsoft.EntityFrameworkCore; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Domain; @@ -10,6 +11,8 @@ namespace Open5ETools.Infrastructure.Data; public class AppDbContext : DbContext, IAppDbContext { + protected readonly JsonSerializerOptions JsonSerializerOptions = new(); + public const string DbProvider = "DbProvider"; public const string Open5ETools = "Open5ETools"; public const string SqliteContext = "sqlite"; @@ -22,16 +25,19 @@ public class AppDbContext : DbContext, IAppDbContext public DbSet Monsters { get; set; } public DbSet Treasures { get; set; } public DbSet Spells { get; set; } + public AppDbContext() { - } + protected AppDbContext(DbContextOptions options) : base(options) { } + public AppDbContext(DbContextOptions options) : base(options) { } + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() @@ -42,21 +48,18 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasIndex(o => new { o.Key, o.Name }) .IsUnique(); - modelBuilder.Entity().OwnsOne( - monster => monster.JsonMonster, ownedNavigationBuilder => - { - ownedNavigationBuilder.ToJson(); - ownedNavigationBuilder.OwnsMany(m => m.SpecialAbilities); - ownedNavigationBuilder.OwnsMany(m => m.Actions); - ownedNavigationBuilder.OwnsMany(m => m.LegendaryActions); - ownedNavigationBuilder.OwnsMany(m => m.Reactions); - }); + modelBuilder.Entity(entity => + { + entity.Property(e => e.JsonMonster) + .HasColumnType("nvarchar(max)") + .HasConversion( + monster => JsonSerializer.Serialize(monster, JsonSerializerOptions), + s => JsonSerializer.Deserialize(s, + JsonSerializerOptions)!); + }); modelBuilder.Entity().OwnsOne( - treasure => treasure.TreasureDescription, ownedNavigationBuilder => - { - ownedNavigationBuilder.ToJson(); - }); + treasure => treasure.TreasureDescription, ownedNavigationBuilder => { ownedNavigationBuilder.ToJson(); }); modelBuilder.UseEnumStringConverter(); } } \ No newline at end of file diff --git a/src/Open5ETools.Infrastructure/Data/AppDbContextInitializer.cs b/src/Open5ETools.Infrastructure/Data/AppDbContextInitializer.cs index f81a835..a289d43 100644 --- a/src/Open5ETools.Infrastructure/Data/AppDbContextInitializer.cs +++ b/src/Open5ETools.Infrastructure/Data/AppDbContextInitializer.cs @@ -1,5 +1,4 @@ -using MapsterMapper; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using Open5ETools.Core.Common.Configurations; using Open5ETools.Core.Common.Enums; @@ -7,8 +6,8 @@ using Open5ETools.Core.Common.Helpers; using Open5ETools.Core.Common.Interfaces.Data; using Open5ETools.Core.Common.Interfaces.Services.DM; +using Open5ETools.Core.Common.Mappers; using Open5ETools.Core.Common.Models.DM.Generator; -using Open5ETools.Core.Common.Models.DM.Services; using Open5ETools.Core.Common.Models.Json; using Open5ETools.Core.Domain; using Open5ETools.Core.Domain.DM; @@ -17,12 +16,10 @@ namespace Open5ETools.Infrastructure.Data; public class AppDbContextInitializer( - IMapper mapper, IAppDbContext context, IDungeonService dungeonService, IOptions config) { - private readonly IMapper _mapper = mapper; private readonly IAppDbContext _context = context; private readonly IDungeonService _dungeonService = dungeonService; public const int TestAdminUserId = 1; @@ -72,7 +69,7 @@ public async Task SeedTestBaseAsync(CancellationToken cancellationToken) private async Task SeedSpellsAsync(CancellationToken cancellationToken) { var spells = JsonHelper.DeserializeJson(JsonHelper.SpellFileName); - var spellEntities = spells.Select(spell => _mapper.Map(spell)).ToList(); + var spellEntities = spells.Select(spell => spell.ToEntity()); await _context.Spells.AddRangeAsync(spellEntities, cancellationToken); await _context.SaveChangesAsync(cancellationToken); @@ -81,7 +78,14 @@ private async Task SeedSpellsAsync(CancellationToken cancellationToken) private async Task SeedTreasuresAsync(CancellationToken cancellationToken) { var treasures = JsonHelper.DeserializeJson(JsonHelper.TreasureFileName); - var treasureEntities = treasures.Select(treasure => new Treasure { TreasureDescription = treasure }).ToList(); + var treasureEntities = treasures.Select(treasure => new + Treasure + { + TreasureDescription = treasure, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty + } + ).ToArray(); await _context.Treasures.AddRangeAsync(treasureEntities, cancellationToken); await _context.SaveChangesAsync(cancellationToken); @@ -90,7 +94,12 @@ private async Task SeedTreasuresAsync(CancellationToken cancellationToken) private async Task SeedMonstersAsync(CancellationToken cancellationToken) { var monsters = JsonHelper.DeserializeJson(JsonHelper.MonsterFileName); - var monsterEntities = monsters.Select(monster => new Core.Domain.EG.Monster { JsonMonster = monster }).ToList(); + var monsterEntities = monsters.Select(monster => new Core.Domain.EG.Monster + { + JsonMonster = monster, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty + }).ToArray(); await _context.Monsters.AddRangeAsync(monsterEntities, cancellationToken); await _context.SaveChangesAsync(cancellationToken); @@ -489,35 +498,16 @@ private async Task SeedDungeonsAsync(int userId, CancellationToken token) TreasureValue = 1, RoomDensity = 10, RoomSize = 20, - Corridor = true + Corridor = true, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty }; _context.DungeonOptions.Add(dungeonOption); await _context.SaveChangesAsync(token); - - var model = new DungeonOptionModel - { - DungeonName = dungeonOption.DungeonName, - Created = dungeonOption.Created, - ItemsRarity = dungeonOption.ItemsRarity, - DeadEnd = dungeonOption.DeadEnd, - DungeonDifficulty = dungeonOption.DungeonDifficulty, - DungeonSize = dungeonOption.DungeonSize, - MonsterType = dungeonOption.MonsterType, - PartyLevel = dungeonOption.PartyLevel, - PartySize = dungeonOption.PartySize, - TrapPercent = dungeonOption.TrapPercent, - RoamingPercent = dungeonOption.RoamingPercent, - TreasureValue = dungeonOption.TreasureValue, - RoomDensity = dungeonOption.RoomDensity, - RoomSize = dungeonOption.RoomSize, - Corridor = dungeonOption.Corridor, - Id = dungeonOption.Id, - UserId = dungeonOption.UserId - }; - + var model = dungeonOption.ToModel(); var sd = await _dungeonService.GenerateDungeonAsync(model, token); - sd.Level = 1; + sd = sd with { Level = 1 }; await _dungeonService.AddDungeonAsync(sd, token); dungeonOption = new DungeonOption @@ -537,34 +527,15 @@ private async Task SeedDungeonsAsync(int userId, CancellationToken token) TreasureValue = 1, RoomDensity = 10, RoomSize = 20, - Corridor = false + Corridor = false, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty }; _context.DungeonOptions.Add(dungeonOption); await _context.SaveChangesAsync(token); - - model = new DungeonOptionModel - { - DungeonName = dungeonOption.DungeonName, - Created = dungeonOption.Created, - ItemsRarity = dungeonOption.ItemsRarity, - DeadEnd = dungeonOption.DeadEnd, - DungeonDifficulty = dungeonOption.DungeonDifficulty, - DungeonSize = dungeonOption.DungeonSize, - MonsterType = dungeonOption.MonsterType, - PartyLevel = dungeonOption.PartyLevel, - PartySize = dungeonOption.PartySize, - TrapPercent = dungeonOption.TrapPercent, - RoamingPercent = dungeonOption.RoamingPercent, - TreasureValue = dungeonOption.TreasureValue, - RoomDensity = dungeonOption.RoomDensity, - RoomSize = dungeonOption.RoomSize, - Corridor = dungeonOption.Corridor, - Id = dungeonOption.Id, - UserId = dungeonOption.UserId - }; - + model = dungeonOption.ToModel(); sd = await _dungeonService.GenerateDungeonAsync(model, token); - sd.Level = 1; + sd = sd with { Level = 1 }; await _dungeonService.AddDungeonAsync(sd, token); } @@ -578,7 +549,9 @@ private async Task SeedUsersAsync(CancellationToken token, bool seedDeletedUtUse FirstName = "Test", LastName = "Admin", Email = "admin@admin.com", - Role = Role.Admin + Role = Role.Admin, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty }); _context.Users.Add(new User @@ -589,7 +562,9 @@ private async Task SeedUsersAsync(CancellationToken token, bool seedDeletedUtUse FirstName = "Test", LastName = "User", Email = "user@user.com", - Role = Role.User + Role = Role.User, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty }); if (seedDeletedUtUser) @@ -603,7 +578,9 @@ private async Task SeedUsersAsync(CancellationToken token, bool seedDeletedUtUse LastName = "User", Email = "user@user.com", Role = Role.User, - IsDeleted = true + IsDeleted = true, + CreatedBy = string.Empty, + LastModifiedBy = string.Empty }); } diff --git a/src/Open5ETools.Infrastructure/Data/SqliteContext.cs b/src/Open5ETools.Infrastructure/Data/SqliteContext.cs index e788979..e1b1008 100644 --- a/src/Open5ETools.Infrastructure/Data/SqliteContext.cs +++ b/src/Open5ETools.Infrastructure/Data/SqliteContext.cs @@ -1,22 +1,25 @@ -using Microsoft.EntityFrameworkCore; +using System.Text.Json; +using Microsoft.EntityFrameworkCore; using Open5ETools.Core.Domain; using Open5ETools.Core.Domain.DM; using Open5ETools.Core.Domain.EG; using Open5ETools.Core.Domain.SM; namespace Open5ETools.Infrastructure.Data; + public class SqliteContext : AppDbContext { private const string CurrentTimestamp = "CURRENT_TIMESTAMP"; public const string HomeToken = "%HOME%"; + public SqliteContext() { - } + public SqliteContext(DbContextOptions options) : base(options) { - } + protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().Metadata.UseSqlReturningClause(false); @@ -42,36 +45,31 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().Metadata.UseSqlReturningClause(false); modelBuilder.Entity() - .Property(p => p.Timestamp) + .Property(p => p.Timestamp) .IsRowVersion() .HasDefaultValueSql(CurrentTimestamp); + modelBuilder.Entity() - .OwnsOne( - monster => monster.JsonMonster, ownedNavigationBuilder => - { - ownedNavigationBuilder.ToJson(); - ownedNavigationBuilder.OwnsMany(m => m.SpecialAbilities); - ownedNavigationBuilder.OwnsMany(m => m.Actions); - ownedNavigationBuilder.OwnsMany(m => m.LegendaryActions); - ownedNavigationBuilder.OwnsMany(m => m.Reactions); - }); + .Property(m => m.JsonMonster) + .HasConversion( + monster => JsonSerializer.Serialize(monster, JsonSerializerOptions), + v => JsonSerializer.Deserialize(v, JsonSerializerOptions)! + ) + .HasColumnType("TEXT"); modelBuilder.Entity().Metadata.UseSqlReturningClause(false); modelBuilder.Entity() - .Property(p => p.Timestamp) + .Property(p => p.Timestamp) .IsRowVersion() .HasDefaultValueSql(CurrentTimestamp); modelBuilder.Entity().OwnsOne( - treasure => treasure.TreasureDescription, ownedNavigationBuilder => - { - ownedNavigationBuilder.ToJson(); - }); + treasure => treasure.TreasureDescription, ownedNavigationBuilder => { ownedNavigationBuilder.ToJson(); }); modelBuilder.Entity().Metadata.UseSqlReturningClause(false); modelBuilder.Entity() .Property(p => p.Timestamp) .IsRowVersion() - .HasDefaultValueSql(CurrentTimestamp); + .HasDefaultValueSql(CurrentTimestamp); } #if DEBUG diff --git a/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20240311201112_Init.Designer.cs b/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20240311201112_Init.Designer.cs deleted file mode 100644 index a4258de..0000000 --- a/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20240311201112_Init.Designer.cs +++ /dev/null @@ -1,843 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Open5ETools.Infrastructure.Data; - -#nullable disable - -namespace Open5ETools.Infrastructure.Migrations.SqlServerMigrations -{ - [DbContext(typeof(SqlServerContext))] - [Migration("20240311201112_Init")] - partial class Init - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.2") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DungeonOptionId") - .HasColumnType("int"); - - b.Property("DungeonTiles") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Level") - .HasColumnType("int"); - - b.Property("RoamingMonsterDescription") - .HasColumnType("nvarchar(max)"); - - b.Property("RoomDescription") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("rowversion"); - - b.Property("TrapDescription") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("DungeonOptionId"); - - b.ToTable("Dungeons"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Corridor") - .HasColumnType("bit"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("DeadEnd") - .HasColumnType("bit"); - - b.Property("DungeonDifficulty") - .HasColumnType("int"); - - b.Property("DungeonName") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("DungeonSize") - .HasColumnType("int"); - - b.Property("ItemsRarity") - .HasColumnType("int"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("MonsterType") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("PartyLevel") - .HasColumnType("int"); - - b.Property("PartySize") - .HasColumnType("int"); - - b.Property("RoamingPercent") - .HasColumnType("int"); - - b.Property("RoomDensity") - .HasColumnType("int"); - - b.Property("RoomSize") - .HasColumnType("int"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("rowversion"); - - b.Property("TrapPercent") - .HasColumnType("int"); - - b.Property("TreasureValue") - .HasColumnType("float"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("DungeonName", "UserId") - .IsUnique(); - - b.ToTable("DungeonOptions"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Option", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Key") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("rowversion"); - - b.Property("Value") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("Key", "Name") - .IsUnique(); - - b.ToTable("Options"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("rowversion"); - - b.HasKey("Id"); - - b.ToTable("Treasures"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("rowversion"); - - b.HasKey("Id"); - - b.ToTable("Monsters"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.SM.Spell", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Archetype") - .HasColumnType("nvarchar(max)"); - - b.Property("CastingTime") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Circles") - .HasColumnType("nvarchar(max)"); - - b.Property("Class") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Components") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Concentration") - .HasColumnType("bit"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Desc") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Domains") - .HasColumnType("nvarchar(max)"); - - b.Property("Duration") - .HasColumnType("nvarchar(max)"); - - b.Property("HigherLevel") - .HasColumnType("nvarchar(max)"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Level") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Material") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Oaths") - .HasColumnType("nvarchar(max)"); - - b.Property("Page") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Patrons") - .HasColumnType("nvarchar(max)"); - - b.Property("Range") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Ritual") - .HasColumnType("bit"); - - b.Property("School") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("rowversion"); - - b.HasKey("Id"); - - b.ToTable("Spells"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Password") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Role") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("rowversion"); - - b.Property("Username") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => - { - b.HasOne("Open5ETools.Core.Domain.DM.DungeonOption", "DungeonOption") - .WithMany("Dungeons") - .HasForeignKey("DungeonOptionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("DungeonOption"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.HasOne("Open5ETools.Core.Domain.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => - { - b1.Property("TreasureId") - .HasColumnType("int"); - - b1.Property("Cost") - .HasColumnType("int"); - - b1.Property("Magical") - .HasColumnType("bit"); - - b1.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.Property("Rarity") - .HasColumnType("int"); - - b1.Property("Types") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b1.HasKey("TreasureId"); - - b1.ToTable("Treasures"); - - b1.ToJson("TreasureDescription"); - - b1.WithOwner() - .HasForeignKey("TreasureId"); - }); - - b.Navigation("TreasureDescription") - .IsRequired(); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.Json.Monster", "JsonMonster", b1 => - { - b1.Property("MonsterId") - .HasColumnType("int"); - - b1.Property("Acrobatics") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "acrobatics"); - - b1.Property("Alignment") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "alignment"); - - b1.Property("Arcana") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "arcana"); - - b1.Property("ArmorClass") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "armor_class"); - - b1.Property("Athletics") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "athletics"); - - b1.Property("ChallengeRating") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "challenge_rating"); - - b1.Property("Charisma") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "charisma"); - - b1.Property("CharismaSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "charisma_save"); - - b1.Property("ConditionImmunities") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "condition_immunities"); - - b1.Property("Constitution") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "constitution"); - - b1.Property("ConstitutionSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "constitution_save"); - - b1.Property("DamageImmunities") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_immunities"); - - b1.Property("DamageResistances") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_resistances"); - - b1.Property("DamageVulnerabilities") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_vulnerabilities"); - - b1.Property("Deception") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "deception"); - - b1.Property("Dexterity") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "dexterity"); - - b1.Property("DexteritySave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "dexterity_save"); - - b1.Property("History") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "history"); - - b1.Property("HitDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "hit_dice"); - - b1.Property("HitPoints") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "hit_points"); - - b1.Property("Insight") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "insight"); - - b1.Property("Intelligence") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "intelligence"); - - b1.Property("IntelligenceSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "intelligence_save"); - - b1.Property("Intimidation") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "intimidation"); - - b1.Property("Investigation") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "investigation"); - - b1.Property("Languages") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "languages"); - - b1.Property("Medicine") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "medicine"); - - b1.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b1.Property("Nature") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "nature"); - - b1.Property("Perception") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "perception"); - - b1.Property("Performance") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "performance"); - - b1.Property("Persuasion") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "persuasion"); - - b1.Property("Religion") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "religion"); - - b1.Property("Senses") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "senses"); - - b1.Property("Size") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "size"); - - b1.Property("Speed") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "speed"); - - b1.Property("Stealth") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "stealth"); - - b1.Property("Strength") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "strength"); - - b1.Property("StrengthSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "strength_save"); - - b1.Property("Subtype") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "subtype"); - - b1.Property("Survival") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "survival"); - - b1.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "type"); - - b1.Property("Wisdom") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "wisdom"); - - b1.Property("WisdomSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "wisdom_save"); - - b1.HasKey("MonsterId"); - - b1.ToTable("Monsters"); - - b1.ToJson("JsonMonster"); - - b1.WithOwner() - .HasForeignKey("MonsterId"); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Action", "Actions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "damage_bonus"); - - b2.Property("DamageDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.LegendaryAction", "LegendaryActions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "legendary_actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Reaction", "Reactions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "reactions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.SpecialAbility", "SpecialAbilities", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "special_abilities"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.Navigation("Actions"); - - b1.Navigation("LegendaryActions"); - - b1.Navigation("Reactions"); - - b1.Navigation("SpecialAbilities"); - }); - - b.Navigation("JsonMonster") - .IsRequired(); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.Navigation("Dungeons"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20260222205301_Init.Designer.cs b/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20260222205301_Init.Designer.cs new file mode 100644 index 0000000..a4782fb --- /dev/null +++ b/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20260222205301_Init.Designer.cs @@ -0,0 +1,524 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Open5ETools.Infrastructure.Data; + +#nullable disable + +namespace Open5ETools.Infrastructure.Migrations.SqlServerMigrations +{ + [DbContext(typeof(SqlServerContext))] + [Migration("20260222205301_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DungeonOptionId") + .HasColumnType("int"); + + b.Property("DungeonTiles") + .IsRequired() + .HasMaxLength(2147483647) + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("RoamingMonsterDescription") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("RoomDescription") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.Property("TrapDescription") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("DungeonOptionId"); + + b.ToTable("Dungeons"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Corridor") + .HasColumnType("bit"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("DeadEnd") + .HasColumnType("bit"); + + b.Property("DungeonDifficulty") + .HasColumnType("int"); + + b.Property("DungeonName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(32767)"); + + b.Property("DungeonSize") + .HasColumnType("int"); + + b.Property("ItemsRarity") + .HasColumnType("int"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("MonsterType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PartyLevel") + .HasColumnType("int"); + + b.Property("PartySize") + .HasColumnType("int"); + + b.Property("RoamingPercent") + .HasColumnType("int"); + + b.Property("RoomDensity") + .HasColumnType("int"); + + b.Property("RoomSize") + .HasColumnType("int"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.Property("TrapPercent") + .HasColumnType("int"); + + b.Property("TreasureValue") + .HasColumnType("float"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("DungeonName", "UserId") + .IsUnique(); + + b.ToTable("DungeonOptions"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Option", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Key") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(32767)"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Key", "Name") + .IsUnique(); + + b.ToTable("Options"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.HasKey("Id"); + + b.ToTable("Treasures"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("JsonMonster") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.HasKey("Id"); + + b.ToTable("Monsters"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.SM.Spell", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Archetype") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("CastingTime") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Circles") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Class") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Components") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Concentration") + .HasColumnType("bit"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Desc") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Domains") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Duration") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("HigherLevel") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Level") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Material") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Oaths") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Page") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Patrons") + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Range") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Ritual") + .HasColumnType("bit"); + + b.Property("School") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.HasKey("Id"); + + b.ToTable("Spells"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("LastModified") + .HasColumnType("datetime2"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.Property("Role") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => + { + b.HasOne("Open5ETools.Core.Domain.DM.DungeonOption", "DungeonOption") + .WithMany("Dungeons") + .HasForeignKey("DungeonOptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DungeonOption"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.HasOne("Open5ETools.Core.Domain.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => + { + b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => + { + b1.Property("TreasureId"); + + b1.Property("Cost"); + + b1.Property("Magical"); + + b1.Property("Name") + .IsRequired(); + + b1.Property("Rarity"); + + b1.PrimitiveCollection("Types") + .IsRequired(); + + b1.HasKey("TreasureId"); + + b1.ToTable("Treasures"); + + b1 + .ToJson("TreasureDescription") + .HasColumnType("nvarchar(max)"); + + b1.WithOwner() + .HasForeignKey("TreasureId"); + }); + + b.Navigation("TreasureDescription") + .IsRequired(); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.Navigation("Dungeons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20240311201112_Init.cs b/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20260222205301_Init.cs similarity index 89% rename from src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20240311201112_Init.cs rename to src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20260222205301_Init.cs index cda4a4c..48b4027 100644 --- a/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20240311201112_Init.cs +++ b/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/20260222205301_Init.cs @@ -17,12 +17,12 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), + JsonMonster = table.Column(type: "nvarchar(max)", nullable: false), Timestamp = table.Column(type: "rowversion", rowVersion: true, nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: false), Created = table.Column(type: "datetime2", nullable: false), LastModifiedBy = table.Column(type: "nvarchar(max)", nullable: false), - LastModified = table.Column(type: "datetime2", nullable: false), - JsonMonster = table.Column(type: "nvarchar(max)", nullable: false) + LastModified = table.Column(type: "datetime2", nullable: false) }, constraints: table => { @@ -36,8 +36,8 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), Key = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(450)", nullable: false), - Value = table.Column(type: "nvarchar(max)", nullable: false), + Name = table.Column(type: "nvarchar(32767)", maxLength: 32767, nullable: false), + Value = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), Timestamp = table.Column(type: "rowversion", rowVersion: true, nullable: false) }, constraints: table => @@ -51,25 +51,25 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - Desc = table.Column(type: "nvarchar(max)", nullable: false), - HigherLevel = table.Column(type: "nvarchar(max)", nullable: true), - Page = table.Column(type: "nvarchar(max)", nullable: false), - Range = table.Column(type: "nvarchar(max)", nullable: false), - Components = table.Column(type: "nvarchar(max)", nullable: false), - Material = table.Column(type: "nvarchar(max)", nullable: true), + Name = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Desc = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Page = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Range = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Components = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + CastingTime = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Level = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Class = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + School = table.Column(type: "nvarchar(max)", nullable: false), Ritual = table.Column(type: "bit", nullable: false), - Duration = table.Column(type: "nvarchar(max)", nullable: true), Concentration = table.Column(type: "bit", nullable: false), - CastingTime = table.Column(type: "nvarchar(max)", nullable: false), - Level = table.Column(type: "nvarchar(max)", nullable: false), - School = table.Column(type: "nvarchar(max)", nullable: false), - Class = table.Column(type: "nvarchar(max)", nullable: false), - Archetype = table.Column(type: "nvarchar(max)", nullable: true), - Circles = table.Column(type: "nvarchar(max)", nullable: true), - Domains = table.Column(type: "nvarchar(max)", nullable: true), - Oaths = table.Column(type: "nvarchar(max)", nullable: true), - Patrons = table.Column(type: "nvarchar(max)", nullable: true), + HigherLevel = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), + Material = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), + Duration = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), + Archetype = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), + Circles = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), + Domains = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), + Oaths = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), + Patrons = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), Timestamp = table.Column(type: "rowversion", rowVersion: true, nullable: false), CreatedBy = table.Column(type: "nvarchar(max)", nullable: false), Created = table.Column(type: "datetime2", nullable: false), @@ -105,11 +105,11 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - Username = table.Column(type: "nvarchar(max)", nullable: false), - FirstName = table.Column(type: "nvarchar(max)", nullable: false), - LastName = table.Column(type: "nvarchar(max)", nullable: false), - Email = table.Column(type: "nvarchar(max)", nullable: false), - Password = table.Column(type: "nvarchar(max)", nullable: false), + Username = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + FirstName = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + LastName = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Email = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + Password = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), Role = table.Column(type: "nvarchar(max)", nullable: false), IsDeleted = table.Column(type: "bit", nullable: false), Timestamp = table.Column(type: "rowversion", rowVersion: true, nullable: false), @@ -129,7 +129,7 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - DungeonName = table.Column(type: "nvarchar(450)", nullable: false), + DungeonName = table.Column(type: "nvarchar(32767)", maxLength: 32767, nullable: false), DungeonSize = table.Column(type: "int", nullable: false), DungeonDifficulty = table.Column(type: "int", nullable: false), PartyLevel = table.Column(type: "int", nullable: false), @@ -138,7 +138,7 @@ protected override void Up(MigrationBuilder migrationBuilder) ItemsRarity = table.Column(type: "int", nullable: false), RoomDensity = table.Column(type: "int", nullable: false), RoomSize = table.Column(type: "int", nullable: false), - MonsterType = table.Column(type: "nvarchar(max)", nullable: false), + MonsterType = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), TrapPercent = table.Column(type: "int", nullable: false), DeadEnd = table.Column(type: "bit", nullable: false), Corridor = table.Column(type: "bit", nullable: false), @@ -167,10 +167,10 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - DungeonTiles = table.Column(type: "nvarchar(max)", nullable: false), - RoomDescription = table.Column(type: "nvarchar(max)", nullable: false), - TrapDescription = table.Column(type: "nvarchar(max)", nullable: false), - RoamingMonsterDescription = table.Column(type: "nvarchar(max)", nullable: true), + DungeonTiles = table.Column(type: "nvarchar(max)", maxLength: 2147483647, nullable: false), + RoomDescription = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + TrapDescription = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: false), + RoamingMonsterDescription = table.Column(type: "nvarchar(max)", maxLength: 32767, nullable: true), Level = table.Column(type: "int", nullable: false), DungeonOptionId = table.Column(type: "int", nullable: false), Timestamp = table.Column(type: "rowversion", rowVersion: true, nullable: false), diff --git a/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/SqlServerContextModelSnapshot.cs b/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/SqlServerContextModelSnapshot.cs index 9f7463d..95437bf 100644 --- a/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/SqlServerContextModelSnapshot.cs +++ b/src/Open5ETools.Infrastructure/Migrations/SqlServerMigrations/SqlServerContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("ProductVersion", "10.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -42,6 +42,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("DungeonTiles") .IsRequired() + .HasMaxLength(2147483647) .HasColumnType("nvarchar(max)"); b.Property("LastModified") @@ -55,10 +56,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("int"); b.Property("RoamingMonsterDescription") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("RoomDescription") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Timestamp") @@ -69,6 +72,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("TrapDescription") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -104,7 +108,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("DungeonName") .IsRequired() - .HasColumnType("nvarchar(450)"); + .HasMaxLength(32767) + .HasColumnType("nvarchar(32767)"); b.Property("DungeonSize") .HasColumnType("int"); @@ -121,7 +126,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("MonsterType") .IsRequired() - .HasColumnType("nvarchar(max)"); + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); b.Property("PartyLevel") .HasColumnType("int"); @@ -177,7 +183,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Name") .IsRequired() - .HasColumnType("nvarchar(450)"); + .HasMaxLength(32767) + .HasColumnType("nvarchar(32767)"); b.Property("Timestamp") .IsConcurrencyToken() @@ -187,6 +194,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Value") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -245,6 +253,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("JsonMonster") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("LastModified") .HasColumnType("datetime2"); @@ -272,21 +284,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); b.Property("Archetype") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("CastingTime") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Circles") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Class") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Components") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Concentration") @@ -301,15 +318,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Desc") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Domains") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Duration") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("HigherLevel") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("LastModified") @@ -321,27 +342,34 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Level") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Material") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Name") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Oaths") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Page") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Patrons") + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Range") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Ritual") @@ -379,10 +407,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Email") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("FirstName") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("IsDeleted") @@ -397,10 +427,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastName") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Password") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.Property("Role") @@ -415,6 +447,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Username") .IsRequired() + .HasMaxLength(32767) .HasColumnType("nvarchar(max)"); b.HasKey("Id"); @@ -448,31 +481,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => { - b1.Property("TreasureId") - .HasColumnType("int"); + b1.Property("TreasureId"); - b1.Property("Cost") - .HasColumnType("int"); + b1.Property("Cost"); - b1.Property("Magical") - .HasColumnType("bit"); + b1.Property("Magical"); b1.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); + .IsRequired(); - b1.Property("Rarity") - .HasColumnType("int"); + b1.Property("Rarity"); - b1.Property("Types") - .IsRequired() - .HasColumnType("nvarchar(max)"); + b1.PrimitiveCollection("Types") + .IsRequired(); b1.HasKey("TreasureId"); b1.ToTable("Treasures"); - b1.ToJson("TreasureDescription"); + b1 + .ToJson("TreasureDescription") + .HasColumnType("nvarchar(max)"); b1.WithOwner() .HasForeignKey("TreasureId"); @@ -482,354 +511,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); }); - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.Json.Monster", "JsonMonster", b1 => - { - b1.Property("MonsterId") - .HasColumnType("int"); - - b1.Property("Acrobatics") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "acrobatics"); - - b1.Property("Alignment") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "alignment"); - - b1.Property("Arcana") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "arcana"); - - b1.Property("ArmorClass") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "armor_class"); - - b1.Property("Athletics") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "athletics"); - - b1.Property("ChallengeRating") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "challenge_rating"); - - b1.Property("Charisma") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "charisma"); - - b1.Property("CharismaSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "charisma_save"); - - b1.Property("ConditionImmunities") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "condition_immunities"); - - b1.Property("Constitution") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "constitution"); - - b1.Property("ConstitutionSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "constitution_save"); - - b1.Property("DamageImmunities") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_immunities"); - - b1.Property("DamageResistances") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_resistances"); - - b1.Property("DamageVulnerabilities") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_vulnerabilities"); - - b1.Property("Deception") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "deception"); - - b1.Property("Dexterity") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "dexterity"); - - b1.Property("DexteritySave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "dexterity_save"); - - b1.Property("History") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "history"); - - b1.Property("HitDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "hit_dice"); - - b1.Property("HitPoints") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "hit_points"); - - b1.Property("Insight") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "insight"); - - b1.Property("Intelligence") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "intelligence"); - - b1.Property("IntelligenceSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "intelligence_save"); - - b1.Property("Intimidation") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "intimidation"); - - b1.Property("Investigation") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "investigation"); - - b1.Property("Languages") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "languages"); - - b1.Property("Medicine") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "medicine"); - - b1.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b1.Property("Nature") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "nature"); - - b1.Property("Perception") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "perception"); - - b1.Property("Performance") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "performance"); - - b1.Property("Persuasion") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "persuasion"); - - b1.Property("Religion") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "religion"); - - b1.Property("Senses") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "senses"); - - b1.Property("Size") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "size"); - - b1.Property("Speed") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "speed"); - - b1.Property("Stealth") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "stealth"); - - b1.Property("Strength") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "strength"); - - b1.Property("StrengthSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "strength_save"); - - b1.Property("Subtype") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "subtype"); - - b1.Property("Survival") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "survival"); - - b1.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "type"); - - b1.Property("Wisdom") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "wisdom"); - - b1.Property("WisdomSave") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "wisdom_save"); - - b1.HasKey("MonsterId"); - - b1.ToTable("Monsters"); - - b1.ToJson("JsonMonster"); - - b1.WithOwner() - .HasForeignKey("MonsterId"); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Action", "Actions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "damage_bonus"); - - b2.Property("DamageDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.LegendaryAction", "LegendaryActions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "legendary_actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Reaction", "Reactions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "reactions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.SpecialAbility", "SpecialAbilities", b2 => - { - b2.Property("MonsterId") - .HasColumnType("int"); - - b2.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b2.Property("AttackBonus") - .HasColumnType("int") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("nvarchar(max)") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "special_abilities"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.Navigation("Actions"); - - b1.Navigation("LegendaryActions"); - - b1.Navigation("Reactions"); - - b1.Navigation("SpecialAbilities"); - }); - - b.Navigation("JsonMonster") - .IsRequired(); - }); - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => { b.Navigation("Dungeons"); diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201124_Init.Designer.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201124_Init.Designer.cs deleted file mode 100644 index 9d9675d..0000000 --- a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201124_Init.Designer.cs +++ /dev/null @@ -1,836 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Open5ETools.Infrastructure.Data; - -#nullable disable - -namespace Open5ETools.Infrastructure.Migrations.SqliteMigrations -{ - [DbContext(typeof(SqliteContext))] - [Migration("20240311201124_Init")] - partial class Init - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.2"); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DungeonOptionId") - .HasColumnType("INTEGER"); - - b.Property("DungeonTiles") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("INTEGER"); - - b.Property("RoamingMonsterDescription") - .HasColumnType("TEXT"); - - b.Property("RoomDescription") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("TrapDescription") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DungeonOptionId"); - - b.ToTable("Dungeons"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Corridor") - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DeadEnd") - .HasColumnType("INTEGER"); - - b.Property("DungeonDifficulty") - .HasColumnType("INTEGER"); - - b.Property("DungeonName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DungeonSize") - .HasColumnType("INTEGER"); - - b.Property("ItemsRarity") - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("MonsterType") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PartyLevel") - .HasColumnType("INTEGER"); - - b.Property("PartySize") - .HasColumnType("INTEGER"); - - b.Property("RoamingPercent") - .HasColumnType("INTEGER"); - - b.Property("RoomDensity") - .HasColumnType("INTEGER"); - - b.Property("RoomSize") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("TrapPercent") - .HasColumnType("INTEGER"); - - b.Property("TreasureValue") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("DungeonOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Option", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Key") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Options"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.HasKey("Id"); - - b.ToTable("Treasures"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.HasKey("Id"); - - b.ToTable("Monsters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.SM.Spell", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Archetype") - .HasColumnType("TEXT"); - - b.Property("CastingTime") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Circles") - .HasColumnType("TEXT"); - - b.Property("Class") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Components") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Concentration") - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Desc") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Domains") - .HasColumnType("TEXT"); - - b.Property("Duration") - .HasColumnType("TEXT"); - - b.Property("HigherLevel") - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Level") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Material") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Oaths") - .HasColumnType("TEXT"); - - b.Property("Page") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Patrons") - .HasColumnType("TEXT"); - - b.Property("Range") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Ritual") - .HasColumnType("INTEGER"); - - b.Property("School") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.HasKey("Id"); - - b.ToTable("Spells"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Email") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Password") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Role") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("Username") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => - { - b.HasOne("Open5ETools.Core.Domain.DM.DungeonOption", "DungeonOption") - .WithMany("Dungeons") - .HasForeignKey("DungeonOptionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("DungeonOption"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.HasOne("Open5ETools.Core.Domain.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => - { - b1.Property("TreasureId") - .HasColumnType("INTEGER"); - - b1.Property("Cost") - .HasColumnType("INTEGER"); - - b1.Property("Magical") - .HasColumnType("INTEGER"); - - b1.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b1.Property("Rarity") - .HasColumnType("INTEGER"); - - b1.Property("Types") - .IsRequired() - .HasColumnType("TEXT"); - - b1.HasKey("TreasureId"); - - b1.ToTable("Treasures"); - - b1.ToJson("TreasureDescription"); - - b1.WithOwner() - .HasForeignKey("TreasureId"); - }); - - b.Navigation("TreasureDescription") - .IsRequired(); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.Json.Monster", "JsonMonster", b1 => - { - b1.Property("MonsterId") - .HasColumnType("INTEGER"); - - b1.Property("Acrobatics") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "acrobatics"); - - b1.Property("Alignment") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "alignment"); - - b1.Property("Arcana") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "arcana"); - - b1.Property("ArmorClass") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "armor_class"); - - b1.Property("Athletics") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "athletics"); - - b1.Property("ChallengeRating") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "challenge_rating"); - - b1.Property("Charisma") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "charisma"); - - b1.Property("CharismaSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "charisma_save"); - - b1.Property("ConditionImmunities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "condition_immunities"); - - b1.Property("Constitution") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "constitution"); - - b1.Property("ConstitutionSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "constitution_save"); - - b1.Property("DamageImmunities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_immunities"); - - b1.Property("DamageResistances") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_resistances"); - - b1.Property("DamageVulnerabilities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_vulnerabilities"); - - b1.Property("Deception") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "deception"); - - b1.Property("Dexterity") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "dexterity"); - - b1.Property("DexteritySave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "dexterity_save"); - - b1.Property("History") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "history"); - - b1.Property("HitDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "hit_dice"); - - b1.Property("HitPoints") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "hit_points"); - - b1.Property("Insight") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "insight"); - - b1.Property("Intelligence") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intelligence"); - - b1.Property("IntelligenceSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intelligence_save"); - - b1.Property("Intimidation") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intimidation"); - - b1.Property("Investigation") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "investigation"); - - b1.Property("Languages") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "languages"); - - b1.Property("Medicine") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "medicine"); - - b1.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b1.Property("Nature") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "nature"); - - b1.Property("Perception") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "perception"); - - b1.Property("Performance") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "performance"); - - b1.Property("Persuasion") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "persuasion"); - - b1.Property("Religion") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "religion"); - - b1.Property("Senses") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "senses"); - - b1.Property("Size") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "size"); - - b1.Property("Speed") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "speed"); - - b1.Property("Stealth") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "stealth"); - - b1.Property("Strength") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "strength"); - - b1.Property("StrengthSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "strength_save"); - - b1.Property("Subtype") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "subtype"); - - b1.Property("Survival") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "survival"); - - b1.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "type"); - - b1.Property("Wisdom") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "wisdom"); - - b1.Property("WisdomSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "wisdom_save"); - - b1.HasKey("MonsterId"); - - b1.ToTable("Monsters"); - - b1.ToJson("JsonMonster"); - - b1.WithOwner() - .HasForeignKey("MonsterId"); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Action", "Actions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "damage_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.LegendaryAction", "LegendaryActions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "legendary_actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Reaction", "Reactions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "reactions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.SpecialAbility", "SpecialAbilities", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "special_abilities"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.Navigation("Actions"); - - b1.Navigation("LegendaryActions"); - - b1.Navigation("Reactions"); - - b1.Navigation("SpecialAbilities"); - }); - - b.Navigation("JsonMonster") - .IsRequired(); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.Navigation("Dungeons"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201134_AddTriggers.Designer.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201134_AddTriggers.Designer.cs deleted file mode 100644 index 2855bcd..0000000 --- a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201134_AddTriggers.Designer.cs +++ /dev/null @@ -1,836 +0,0 @@ -// -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Open5ETools.Infrastructure.Data; - -#nullable disable - -namespace Open5ETools.Infrastructure.Migrations.SqliteMigrations -{ - [DbContext(typeof(SqliteContext))] - [Migration("20240311201134_AddTriggers")] - partial class AddTriggers - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.2"); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DungeonOptionId") - .HasColumnType("INTEGER"); - - b.Property("DungeonTiles") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("INTEGER"); - - b.Property("RoamingMonsterDescription") - .HasColumnType("TEXT"); - - b.Property("RoomDescription") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("TrapDescription") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DungeonOptionId"); - - b.ToTable("Dungeons"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Corridor") - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DeadEnd") - .HasColumnType("INTEGER"); - - b.Property("DungeonDifficulty") - .HasColumnType("INTEGER"); - - b.Property("DungeonName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DungeonSize") - .HasColumnType("INTEGER"); - - b.Property("ItemsRarity") - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("MonsterType") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PartyLevel") - .HasColumnType("INTEGER"); - - b.Property("PartySize") - .HasColumnType("INTEGER"); - - b.Property("RoamingPercent") - .HasColumnType("INTEGER"); - - b.Property("RoomDensity") - .HasColumnType("INTEGER"); - - b.Property("RoomSize") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("TrapPercent") - .HasColumnType("INTEGER"); - - b.Property("TreasureValue") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("DungeonOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Option", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Key") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Options"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.HasKey("Id"); - - b.ToTable("Treasures"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.HasKey("Id"); - - b.ToTable("Monsters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.SM.Spell", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Archetype") - .HasColumnType("TEXT"); - - b.Property("CastingTime") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Circles") - .HasColumnType("TEXT"); - - b.Property("Class") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Components") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Concentration") - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Desc") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Domains") - .HasColumnType("TEXT"); - - b.Property("Duration") - .HasColumnType("TEXT"); - - b.Property("HigherLevel") - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Level") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Material") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Oaths") - .HasColumnType("TEXT"); - - b.Property("Page") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Patrons") - .HasColumnType("TEXT"); - - b.Property("Range") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Ritual") - .HasColumnType("INTEGER"); - - b.Property("School") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.HasKey("Id"); - - b.ToTable("Spells"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Created") - .HasColumnType("TEXT"); - - b.Property("CreatedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Email") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("IsDeleted") - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("LastModifiedBy") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("LastName") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Password") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Role") - .HasColumnType("INTEGER"); - - b.Property("Timestamp") - .IsConcurrencyToken() - .IsRequired() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("BLOB") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("Username") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => - { - b.HasOne("Open5ETools.Core.Domain.DM.DungeonOption", "DungeonOption") - .WithMany("Dungeons") - .HasForeignKey("DungeonOptionId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("DungeonOption"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.HasOne("Open5ETools.Core.Domain.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => - { - b1.Property("TreasureId") - .HasColumnType("INTEGER"); - - b1.Property("Cost") - .HasColumnType("INTEGER"); - - b1.Property("Magical") - .HasColumnType("INTEGER"); - - b1.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b1.Property("Rarity") - .HasColumnType("INTEGER"); - - b1.Property("Types") - .IsRequired() - .HasColumnType("TEXT"); - - b1.HasKey("TreasureId"); - - b1.ToTable("Treasures"); - - b1.ToJson("TreasureDescription"); - - b1.WithOwner() - .HasForeignKey("TreasureId"); - }); - - b.Navigation("TreasureDescription") - .IsRequired(); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.Json.Monster", "JsonMonster", b1 => - { - b1.Property("MonsterId") - .HasColumnType("INTEGER"); - - b1.Property("Acrobatics") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "acrobatics"); - - b1.Property("Alignment") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "alignment"); - - b1.Property("Arcana") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "arcana"); - - b1.Property("ArmorClass") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "armor_class"); - - b1.Property("Athletics") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "athletics"); - - b1.Property("ChallengeRating") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "challenge_rating"); - - b1.Property("Charisma") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "charisma"); - - b1.Property("CharismaSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "charisma_save"); - - b1.Property("ConditionImmunities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "condition_immunities"); - - b1.Property("Constitution") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "constitution"); - - b1.Property("ConstitutionSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "constitution_save"); - - b1.Property("DamageImmunities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_immunities"); - - b1.Property("DamageResistances") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_resistances"); - - b1.Property("DamageVulnerabilities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_vulnerabilities"); - - b1.Property("Deception") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "deception"); - - b1.Property("Dexterity") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "dexterity"); - - b1.Property("DexteritySave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "dexterity_save"); - - b1.Property("History") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "history"); - - b1.Property("HitDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "hit_dice"); - - b1.Property("HitPoints") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "hit_points"); - - b1.Property("Insight") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "insight"); - - b1.Property("Intelligence") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intelligence"); - - b1.Property("IntelligenceSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intelligence_save"); - - b1.Property("Intimidation") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intimidation"); - - b1.Property("Investigation") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "investigation"); - - b1.Property("Languages") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "languages"); - - b1.Property("Medicine") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "medicine"); - - b1.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b1.Property("Nature") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "nature"); - - b1.Property("Perception") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "perception"); - - b1.Property("Performance") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "performance"); - - b1.Property("Persuasion") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "persuasion"); - - b1.Property("Religion") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "religion"); - - b1.Property("Senses") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "senses"); - - b1.Property("Size") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "size"); - - b1.Property("Speed") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "speed"); - - b1.Property("Stealth") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "stealth"); - - b1.Property("Strength") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "strength"); - - b1.Property("StrengthSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "strength_save"); - - b1.Property("Subtype") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "subtype"); - - b1.Property("Survival") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "survival"); - - b1.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "type"); - - b1.Property("Wisdom") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "wisdom"); - - b1.Property("WisdomSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "wisdom_save"); - - b1.HasKey("MonsterId"); - - b1.ToTable("Monsters"); - - b1.ToJson("JsonMonster"); - - b1.WithOwner() - .HasForeignKey("MonsterId"); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Action", "Actions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "damage_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.LegendaryAction", "LegendaryActions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "legendary_actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Reaction", "Reactions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "reactions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.SpecialAbility", "SpecialAbilities", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "special_abilities"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.Navigation("Actions"); - - b1.Navigation("LegendaryActions"); - - b1.Navigation("Reactions"); - - b1.Navigation("SpecialAbilities"); - }); - - b.Navigation("JsonMonster") - .IsRequired(); - }); - - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => - { - b.Navigation("Dungeons"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201134_AddTriggers.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201134_AddTriggers.cs deleted file mode 100644 index 1fc6073..0000000 --- a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201134_AddTriggers.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Open5ETools.Infrastructure.Migrations.SqliteMigrations -{ - /// - public partial class AddTriggers : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - var tables = new[] { "Users", "Dungeons", "DungeonOptions", "Options", "Monsters", "Treasures", "Spells" }; - foreach (var table in tables) - { - migrationBuilder.Sql( - @$" - CREATE TRIGGER Set{table}TimestampOnUpdate - AFTER UPDATE ON {table} - BEGIN - UPDATE {table} - SET Timestamp = randomblob(8) - WHERE rowid = NEW.rowid; - END - "); - migrationBuilder.Sql( - @$" - CREATE TRIGGER Set{table}TimestampOnInsert - AFTER INSERT ON {table} - BEGIN - UPDATE {table} - SET Timestamp = randomblob(8) - WHERE rowid = NEW.rowid; - END - "); - } - - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205308_Init.Designer.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205308_Init.Designer.cs new file mode 100644 index 0000000..f4e6c71 --- /dev/null +++ b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205308_Init.Designer.cs @@ -0,0 +1,517 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Open5ETools.Infrastructure.Data; + +#nullable disable + +namespace Open5ETools.Infrastructure.Migrations.SqliteMigrations +{ + [DbContext(typeof(SqliteContext))] + [Migration("20260222205308_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.3"); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DungeonOptionId") + .HasColumnType("INTEGER"); + + b.Property("DungeonTiles") + .IsRequired() + .HasMaxLength(2147483647) + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("RoamingMonsterDescription") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("RoomDescription") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("TrapDescription") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DungeonOptionId"); + + b.ToTable("Dungeons"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Corridor") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DeadEnd") + .HasColumnType("INTEGER"); + + b.Property("DungeonDifficulty") + .HasColumnType("INTEGER"); + + b.Property("DungeonName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("DungeonSize") + .HasColumnType("INTEGER"); + + b.Property("ItemsRarity") + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("MonsterType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PartyLevel") + .HasColumnType("INTEGER"); + + b.Property("PartySize") + .HasColumnType("INTEGER"); + + b.Property("RoamingPercent") + .HasColumnType("INTEGER"); + + b.Property("RoomDensity") + .HasColumnType("INTEGER"); + + b.Property("RoomSize") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("TrapPercent") + .HasColumnType("INTEGER"); + + b.Property("TreasureValue") + .HasColumnType("REAL"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("DungeonOptions"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Option", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Options"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.HasKey("Id"); + + b.ToTable("Treasures"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("JsonMonster") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.HasKey("Id"); + + b.ToTable("Monsters"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.SM.Spell", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Archetype") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("CastingTime") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Circles") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Class") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Components") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Concentration") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Desc") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Domains") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Duration") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("HigherLevel") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Level") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Material") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Oaths") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Page") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Patrons") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Range") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Ritual") + .HasColumnType("INTEGER"); + + b.Property("School") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.HasKey("Id"); + + b.ToTable("Spells"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Role") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Users"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => + { + b.HasOne("Open5ETools.Core.Domain.DM.DungeonOption", "DungeonOption") + .WithMany("Dungeons") + .HasForeignKey("DungeonOptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DungeonOption"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.HasOne("Open5ETools.Core.Domain.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => + { + b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => + { + b1.Property("TreasureId"); + + b1.Property("Cost"); + + b1.Property("Magical"); + + b1.Property("Name") + .IsRequired(); + + b1.Property("Rarity"); + + b1.PrimitiveCollection("Types") + .IsRequired(); + + b1.HasKey("TreasureId"); + + b1.ToTable("Treasures"); + + b1 + .ToJson("TreasureDescription") + .HasColumnType("TEXT"); + + b1.WithOwner() + .HasForeignKey("TreasureId"); + }); + + b.Navigation("TreasureDescription") + .IsRequired(); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.Navigation("Dungeons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201124_Init.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205308_Init.cs similarity index 86% rename from src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201124_Init.cs rename to src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205308_Init.cs index 9a03041..c11e904 100644 --- a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20240311201124_Init.cs +++ b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205308_Init.cs @@ -17,12 +17,12 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), + JsonMonster = table.Column(type: "TEXT", nullable: false), Timestamp = table.Column(type: "BLOB", rowVersion: true, nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), CreatedBy = table.Column(type: "TEXT", nullable: false), Created = table.Column(type: "TEXT", nullable: false), LastModifiedBy = table.Column(type: "TEXT", nullable: false), - LastModified = table.Column(type: "TEXT", nullable: false), - JsonMonster = table.Column(type: "TEXT", nullable: false) + LastModified = table.Column(type: "TEXT", nullable: false) }, constraints: table => { @@ -36,8 +36,8 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), Key = table.Column(type: "INTEGER", nullable: false), - Name = table.Column(type: "TEXT", nullable: false), - Value = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Value = table.Column(type: "TEXT", maxLength: 32767, nullable: false), Timestamp = table.Column(type: "BLOB", rowVersion: true, nullable: false, defaultValueSql: "CURRENT_TIMESTAMP") }, constraints: table => @@ -51,25 +51,25 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - Name = table.Column(type: "TEXT", nullable: false), - Desc = table.Column(type: "TEXT", nullable: false), - HigherLevel = table.Column(type: "TEXT", nullable: true), - Page = table.Column(type: "TEXT", nullable: false), - Range = table.Column(type: "TEXT", nullable: false), - Components = table.Column(type: "TEXT", nullable: false), - Material = table.Column(type: "TEXT", nullable: true), + Name = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Desc = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Page = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Range = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Components = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + CastingTime = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Level = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Class = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + School = table.Column(type: "INTEGER", nullable: false), Ritual = table.Column(type: "INTEGER", nullable: false), - Duration = table.Column(type: "TEXT", nullable: true), Concentration = table.Column(type: "INTEGER", nullable: false), - CastingTime = table.Column(type: "TEXT", nullable: false), - Level = table.Column(type: "TEXT", nullable: false), - School = table.Column(type: "INTEGER", nullable: false), - Class = table.Column(type: "TEXT", nullable: false), - Archetype = table.Column(type: "TEXT", nullable: true), - Circles = table.Column(type: "TEXT", nullable: true), - Domains = table.Column(type: "TEXT", nullable: true), - Oaths = table.Column(type: "TEXT", nullable: true), - Patrons = table.Column(type: "TEXT", nullable: true), + HigherLevel = table.Column(type: "TEXT", maxLength: 32767, nullable: true), + Material = table.Column(type: "TEXT", maxLength: 32767, nullable: true), + Duration = table.Column(type: "TEXT", maxLength: 32767, nullable: true), + Archetype = table.Column(type: "TEXT", maxLength: 32767, nullable: true), + Circles = table.Column(type: "TEXT", maxLength: 32767, nullable: true), + Domains = table.Column(type: "TEXT", maxLength: 32767, nullable: true), + Oaths = table.Column(type: "TEXT", maxLength: 32767, nullable: true), + Patrons = table.Column(type: "TEXT", maxLength: 32767, nullable: true), Timestamp = table.Column(type: "BLOB", rowVersion: true, nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), CreatedBy = table.Column(type: "TEXT", nullable: false), Created = table.Column(type: "TEXT", nullable: false), @@ -105,11 +105,11 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - Username = table.Column(type: "TEXT", nullable: false), - FirstName = table.Column(type: "TEXT", nullable: false), - LastName = table.Column(type: "TEXT", nullable: false), - Email = table.Column(type: "TEXT", nullable: false), - Password = table.Column(type: "TEXT", nullable: false), + Username = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + FirstName = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + LastName = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Email = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + Password = table.Column(type: "TEXT", maxLength: 32767, nullable: false), Role = table.Column(type: "INTEGER", nullable: false), IsDeleted = table.Column(type: "INTEGER", nullable: false), Timestamp = table.Column(type: "BLOB", rowVersion: true, nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), @@ -129,7 +129,7 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - DungeonName = table.Column(type: "TEXT", nullable: false), + DungeonName = table.Column(type: "TEXT", maxLength: 32767, nullable: false), DungeonSize = table.Column(type: "INTEGER", nullable: false), DungeonDifficulty = table.Column(type: "INTEGER", nullable: false), PartyLevel = table.Column(type: "INTEGER", nullable: false), @@ -138,7 +138,7 @@ protected override void Up(MigrationBuilder migrationBuilder) ItemsRarity = table.Column(type: "INTEGER", nullable: false), RoomDensity = table.Column(type: "INTEGER", nullable: false), RoomSize = table.Column(type: "INTEGER", nullable: false), - MonsterType = table.Column(type: "TEXT", nullable: false), + MonsterType = table.Column(type: "TEXT", maxLength: 50, nullable: false), TrapPercent = table.Column(type: "INTEGER", nullable: false), DeadEnd = table.Column(type: "INTEGER", nullable: false), Corridor = table.Column(type: "INTEGER", nullable: false), @@ -167,10 +167,10 @@ protected override void Up(MigrationBuilder migrationBuilder) { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - DungeonTiles = table.Column(type: "TEXT", nullable: false), - RoomDescription = table.Column(type: "TEXT", nullable: false), - TrapDescription = table.Column(type: "TEXT", nullable: false), - RoamingMonsterDescription = table.Column(type: "TEXT", nullable: true), + DungeonTiles = table.Column(type: "TEXT", maxLength: 2147483647, nullable: false), + RoomDescription = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + TrapDescription = table.Column(type: "TEXT", maxLength: 32767, nullable: false), + RoamingMonsterDescription = table.Column(type: "TEXT", maxLength: 32767, nullable: true), Level = table.Column(type: "INTEGER", nullable: false), DungeonOptionId = table.Column(type: "INTEGER", nullable: false), Timestamp = table.Column(type: "BLOB", rowVersion: true, nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205315_AddTriggers.Designer.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205315_AddTriggers.Designer.cs new file mode 100644 index 0000000..83c3aab --- /dev/null +++ b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205315_AddTriggers.Designer.cs @@ -0,0 +1,517 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Open5ETools.Infrastructure.Data; + +#nullable disable + +namespace Open5ETools.Infrastructure.Migrations.SqliteMigrations +{ + [DbContext(typeof(SqliteContext))] + [Migration("20260222205315_AddTriggers")] + partial class AddTriggers + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "10.0.3"); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DungeonOptionId") + .HasColumnType("INTEGER"); + + b.Property("DungeonTiles") + .IsRequired() + .HasMaxLength(2147483647) + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("RoamingMonsterDescription") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("RoomDescription") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("TrapDescription") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DungeonOptionId"); + + b.ToTable("Dungeons"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Corridor") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DeadEnd") + .HasColumnType("INTEGER"); + + b.Property("DungeonDifficulty") + .HasColumnType("INTEGER"); + + b.Property("DungeonName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("DungeonSize") + .HasColumnType("INTEGER"); + + b.Property("ItemsRarity") + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("MonsterType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PartyLevel") + .HasColumnType("INTEGER"); + + b.Property("PartySize") + .HasColumnType("INTEGER"); + + b.Property("RoamingPercent") + .HasColumnType("INTEGER"); + + b.Property("RoomDensity") + .HasColumnType("INTEGER"); + + b.Property("RoomSize") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("TrapPercent") + .HasColumnType("INTEGER"); + + b.Property("TreasureValue") + .HasColumnType("REAL"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("DungeonOptions"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Option", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Options"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.HasKey("Id"); + + b.ToTable("Treasures"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("JsonMonster") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.HasKey("Id"); + + b.ToTable("Monsters"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.SM.Spell", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Archetype") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("CastingTime") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Circles") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Class") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Components") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Concentration") + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Desc") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Domains") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Duration") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("HigherLevel") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Level") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Material") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Oaths") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Page") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Patrons") + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Range") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Ritual") + .HasColumnType("INTEGER"); + + b.Property("School") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.HasKey("Id"); + + b.ToTable("Spells"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Created") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("LastModified") + .HasColumnType("TEXT"); + + b.Property("LastModifiedBy") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.Property("Role") + .HasColumnType("INTEGER"); + + b.Property("Timestamp") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("BLOB") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(32767) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Users"); + + b.HasAnnotation("Sqlite:UseSqlReturningClause", false); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => + { + b.HasOne("Open5ETools.Core.Domain.DM.DungeonOption", "DungeonOption") + .WithMany("Dungeons") + .HasForeignKey("DungeonOptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DungeonOption"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.HasOne("Open5ETools.Core.Domain.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.Treasure", b => + { + b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => + { + b1.Property("TreasureId"); + + b1.Property("Cost"); + + b1.Property("Magical"); + + b1.Property("Name") + .IsRequired(); + + b1.Property("Rarity"); + + b1.PrimitiveCollection("Types") + .IsRequired(); + + b1.HasKey("TreasureId"); + + b1.ToTable("Treasures"); + + b1 + .ToJson("TreasureDescription") + .HasColumnType("TEXT"); + + b1.WithOwner() + .HasForeignKey("TreasureId"); + }); + + b.Navigation("TreasureDescription") + .IsRequired(); + }); + + modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => + { + b.Navigation("Dungeons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205315_AddTriggers.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205315_AddTriggers.cs new file mode 100644 index 0000000..e5f5875 --- /dev/null +++ b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/20260222205315_AddTriggers.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Open5ETools.Infrastructure.Migrations.SqliteMigrations +{ + /// + public partial class AddTriggers : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + var tables = new[] { "Users", "Dungeons", "DungeonOptions", "Options", "Monsters", "Treasures", "Spells" }; + foreach (var table in tables) + { + migrationBuilder.Sql( + $""" + CREATE TRIGGER Set{table}TimestampOnUpdate + AFTER UPDATE ON {table} + BEGIN + UPDATE {table} + SET Timestamp = randomblob(8) + WHERE rowid = NEW.rowid; + END + """); + migrationBuilder.Sql( + $""" + CREATE TRIGGER Set{table}TimestampOnInsert + AFTER INSERT ON {table} + BEGIN + UPDATE {table} + SET Timestamp = randomblob(8) + WHERE rowid = NEW.rowid; + END + """); + } + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} \ No newline at end of file diff --git a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/SqliteContextModelSnapshot.cs b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/SqliteContextModelSnapshot.cs index fc3e79a..24626fd 100644 --- a/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/SqliteContextModelSnapshot.cs +++ b/src/Open5ETools.Infrastructure/Migrations/SqliteMigrations/SqliteContextModelSnapshot.cs @@ -15,7 +15,7 @@ partial class SqliteContextModelSnapshot : ModelSnapshot protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.2"); + modelBuilder.HasAnnotation("ProductVersion", "10.0.3"); modelBuilder.Entity("Open5ETools.Core.Domain.DM.Dungeon", b => { @@ -35,6 +35,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("DungeonTiles") .IsRequired() + .HasMaxLength(2147483647) .HasColumnType("TEXT"); b.Property("LastModified") @@ -48,10 +49,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER"); b.Property("RoamingMonsterDescription") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("RoomDescription") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Timestamp") @@ -63,6 +66,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("TrapDescription") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.HasKey("Id"); @@ -98,6 +102,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("DungeonName") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("DungeonSize") @@ -115,6 +120,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("MonsterType") .IsRequired() + .HasMaxLength(50) .HasColumnType("TEXT"); b.Property("PartyLevel") @@ -168,6 +174,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Name") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Timestamp") @@ -179,6 +186,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Value") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.HasKey("Id"); @@ -235,6 +243,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("TEXT"); + b.Property("JsonMonster") + .IsRequired() + .HasColumnType("TEXT"); + b.Property("LastModified") .HasColumnType("TEXT"); @@ -263,21 +275,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER"); b.Property("Archetype") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("CastingTime") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Circles") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Class") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Components") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Concentration") @@ -292,15 +309,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Desc") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Domains") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Duration") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("HigherLevel") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("LastModified") @@ -312,27 +333,34 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Level") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Material") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Name") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Oaths") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Page") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Patrons") + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Range") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Ritual") @@ -370,10 +398,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Email") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("FirstName") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("IsDeleted") @@ -388,10 +418,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("LastName") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Password") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.Property("Role") @@ -406,6 +438,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Username") .IsRequired() + .HasMaxLength(32767) .HasColumnType("TEXT"); b.HasKey("Id"); @@ -441,31 +474,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.OwnsOne("Open5ETools.Core.Common.Models.DM.Generator.TreasureDescription", "TreasureDescription", b1 => { - b1.Property("TreasureId") - .HasColumnType("INTEGER"); + b1.Property("TreasureId"); - b1.Property("Cost") - .HasColumnType("INTEGER"); + b1.Property("Cost"); - b1.Property("Magical") - .HasColumnType("INTEGER"); + b1.Property("Magical"); b1.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); + .IsRequired(); - b1.Property("Rarity") - .HasColumnType("INTEGER"); + b1.Property("Rarity"); - b1.Property("Types") - .IsRequired() - .HasColumnType("TEXT"); + b1.PrimitiveCollection("Types") + .IsRequired(); b1.HasKey("TreasureId"); b1.ToTable("Treasures"); - b1.ToJson("TreasureDescription"); + b1 + .ToJson("TreasureDescription") + .HasColumnType("TEXT"); b1.WithOwner() .HasForeignKey("TreasureId"); @@ -475,354 +504,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); }); - modelBuilder.Entity("Open5ETools.Core.Domain.EG.Monster", b => - { - b.OwnsOne("Open5ETools.Core.Common.Models.Json.Monster", "JsonMonster", b1 => - { - b1.Property("MonsterId") - .HasColumnType("INTEGER"); - - b1.Property("Acrobatics") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "acrobatics"); - - b1.Property("Alignment") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "alignment"); - - b1.Property("Arcana") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "arcana"); - - b1.Property("ArmorClass") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "armor_class"); - - b1.Property("Athletics") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "athletics"); - - b1.Property("ChallengeRating") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "challenge_rating"); - - b1.Property("Charisma") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "charisma"); - - b1.Property("CharismaSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "charisma_save"); - - b1.Property("ConditionImmunities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "condition_immunities"); - - b1.Property("Constitution") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "constitution"); - - b1.Property("ConstitutionSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "constitution_save"); - - b1.Property("DamageImmunities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_immunities"); - - b1.Property("DamageResistances") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_resistances"); - - b1.Property("DamageVulnerabilities") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_vulnerabilities"); - - b1.Property("Deception") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "deception"); - - b1.Property("Dexterity") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "dexterity"); - - b1.Property("DexteritySave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "dexterity_save"); - - b1.Property("History") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "history"); - - b1.Property("HitDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "hit_dice"); - - b1.Property("HitPoints") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "hit_points"); - - b1.Property("Insight") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "insight"); - - b1.Property("Intelligence") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intelligence"); - - b1.Property("IntelligenceSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intelligence_save"); - - b1.Property("Intimidation") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "intimidation"); - - b1.Property("Investigation") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "investigation"); - - b1.Property("Languages") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "languages"); - - b1.Property("Medicine") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "medicine"); - - b1.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b1.Property("Nature") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "nature"); - - b1.Property("Perception") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "perception"); - - b1.Property("Performance") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "performance"); - - b1.Property("Persuasion") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "persuasion"); - - b1.Property("Religion") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "religion"); - - b1.Property("Senses") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "senses"); - - b1.Property("Size") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "size"); - - b1.Property("Speed") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "speed"); - - b1.Property("Stealth") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "stealth"); - - b1.Property("Strength") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "strength"); - - b1.Property("StrengthSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "strength_save"); - - b1.Property("Subtype") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "subtype"); - - b1.Property("Survival") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "survival"); - - b1.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "type"); - - b1.Property("Wisdom") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "wisdom"); - - b1.Property("WisdomSave") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "wisdom_save"); - - b1.HasKey("MonsterId"); - - b1.ToTable("Monsters"); - - b1.ToJson("JsonMonster"); - - b1.WithOwner() - .HasForeignKey("MonsterId"); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Action", "Actions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "damage_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.LegendaryAction", "LegendaryActions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "legendary_actions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.Reaction", "Reactions", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "reactions"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.OwnsMany("Open5ETools.Core.Common.Models.Json.SpecialAbility", "SpecialAbilities", b2 => - { - b2.Property("MonsterId") - .HasColumnType("INTEGER"); - - b2.Property("Id") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("INTEGER"); - - b2.Property("AttackBonus") - .HasColumnType("INTEGER") - .HasAnnotation("Relational:JsonPropertyName", "attack_bonus"); - - b2.Property("DamageDice") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "damage_dice"); - - b2.Property("Desc") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "desc"); - - b2.Property("Name") - .HasColumnType("TEXT") - .HasAnnotation("Relational:JsonPropertyName", "name"); - - b2.HasKey("MonsterId", "Id"); - - b2.ToTable("Monsters"); - - b2.HasAnnotation("Relational:JsonPropertyName", "special_abilities"); - - b2.WithOwner() - .HasForeignKey("MonsterId"); - }); - - b1.Navigation("Actions"); - - b1.Navigation("LegendaryActions"); - - b1.Navigation("Reactions"); - - b1.Navigation("SpecialAbilities"); - }); - - b.Navigation("JsonMonster") - .IsRequired(); - }); - modelBuilder.Entity("Open5ETools.Core.Domain.DM.DungeonOption", b => { b.Navigation("Dungeons"); diff --git a/src/Open5ETools.Web/ConfigureServices.cs b/src/Open5ETools.Web/ConfigureServices.cs index de055c9..cf7a096 100644 --- a/src/Open5ETools.Web/ConfigureServices.cs +++ b/src/Open5ETools.Web/ConfigureServices.cs @@ -6,11 +6,6 @@ using Open5ETools.Web.Services; using Serilog; using System.Globalization; -using Mapster; -using Open5ETools.Core.Common.Models.DM.Services; -using Open5ETools.Core.Common.Models.EG; -using Open5ETools.Web.Models.Dungeon; -using Open5ETools.Web.Models.Encounter; namespace Open5ETools.Web; @@ -51,8 +46,7 @@ public static IServiceCollection AddWebServices(this IServiceCollection services options.AccessDeniedPath = new PathString("/Auth/Forbidden/"); }); - services.ConfigureMapster() - .AddMemoryCache(); + services.AddMemoryCache(); services.AddMvc() #if DEBUG @@ -69,33 +63,6 @@ public static IServiceCollection AddWebServices(this IServiceCollection services return services; } - private static IServiceCollection ConfigureMapster(this IServiceCollection services) - { - services.AddMapster(); - - TypeAdapterConfig - .NewConfig() - .Map(dest => dest.Sizes, src => src.SelectedSizes) - .Map(dest => dest.MonsterTypes, src => src.SelectedMonsterTypes); - - TypeAdapterConfig - .NewConfig() - .Map(dest => dest.TreasureValue, src => Convert.ToDouble(src.TreasureValue, CultureInfo.InvariantCulture)) - .Ignore(dest => dest.MonsterType); - - TypeAdapterConfig - .NewConfig() - .Map(dest => dest.TreasureValue, src => src.TreasureValue.ToString(CultureInfo.InvariantCulture)) - .Map(dest => dest.MonsterType, src => GetMonsters(src)); - - return services; - } - - private static string[] GetMonsters(DungeonOptionModel model) - { - return model.MonsterType.Split(','); - } - public static IHostBuilder AddSerilog(this IHostBuilder host, IConfiguration configuration) { diff --git a/src/Open5ETools.Web/Controllers/Auth/AuthController.cs b/src/Open5ETools.Web/Controllers/Auth/AuthController.cs index d32f4a4..56d727c 100644 --- a/src/Open5ETools.Web/Controllers/Auth/AuthController.cs +++ b/src/Open5ETools.Web/Controllers/Auth/AuthController.cs @@ -1,19 +1,16 @@ -using MapsterMapper; using IdentityModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc; using Open5ETools.Core.Common.Interfaces.Services; -using Open5ETools.Core.Common.Models.Services; using Open5ETools.Web.Models.Auth; using System.Security.Claims; namespace Open5ETools.Web.Controllers.Auth; -public class AuthController(IAuthService authService, IMapper mapper) : Controller +public class AuthController(IAuthService authService) : Controller { private readonly IAuthService _authService = authService; - private readonly IMapper _mapper = mapper; public IActionResult Login() { @@ -21,14 +18,16 @@ public IActionResult Login() { return RedirectToAction("Index", "Dungeon"); } + return View(); } + [HttpPost] public async Task Login(LoginViewModel model, string? returnUrl, CancellationToken cancellationToken) { if (ModelState.IsValid) { - var user = await _authService.LoginAsync(_mapper.Map(model), cancellationToken); + var user = await _authService.LoginAsync(model.Username, model.Password, cancellationToken); if (user is null) { @@ -44,9 +43,11 @@ public async Task Login(LoginViewModel model, string? returnUrl, C new(JwtClaimTypes.Role, user.Role) }; - var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme, JwtClaimTypes.Subject, JwtClaimTypes.Role); + var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme, + JwtClaimTypes.Subject, JwtClaimTypes.Role); - var authProperties = (await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme)).Properties; + var authProperties = + (await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme)).Properties; await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(userIdentity), @@ -56,8 +57,10 @@ await HttpContext.SignInAsync( return RedirectToAction("Index", "Dungeon"); return Redirect(returnUrl); } + return View(); } + public async Task Logout() { await HttpContext.SignOutAsync(); diff --git a/src/Open5ETools.Web/Controllers/Web/DungeonController.cs b/src/Open5ETools.Web/Controllers/Web/DungeonController.cs index b995528..0626f9d 100644 --- a/src/Open5ETools.Web/Controllers/Web/DungeonController.cs +++ b/src/Open5ETools.Web/Controllers/Web/DungeonController.cs @@ -1,4 +1,3 @@ -using MapsterMapper; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; @@ -6,12 +5,12 @@ using Open5ETools.Core.Common.Helpers; using Open5ETools.Core.Common.Interfaces.Services; using Open5ETools.Core.Common.Interfaces.Services.DM; -using Open5ETools.Core.Common.Models.DM.Services; using Open5ETools.Web.Models.Dungeon; using System.Text.Json; using Open5ETools.Core.Common.Exceptions; using Open5ETools.Resources; using Open5ETools.Web.Extensions; +using Open5ETools.Web.Mappers; namespace Open5ETools.Web.Controllers.Web; @@ -20,13 +19,12 @@ public class DungeonController( IDungeonService dungeonService, IOptionService optionService, ICurrentUserService currentUserService, - IMapper mapper, - ILogger logger) : Controller + ILogger logger +) : Controller { private readonly IOptionService _optionService = optionService; private readonly IDungeonService _dungeonService = dungeonService; private readonly ICurrentUserService _currentUserService = currentUserService; - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; public async Task Index(CancellationToken cancellationToken) @@ -36,7 +34,7 @@ await _dungeonService.GetAllDungeonOptionsForUserAsync(_currentUserService.GetUs cancellationToken); var model = new DungeonListViewModel { - List = list.Select(_mapper.Map) + List = [.. list.Select(dom => dom.ToViewModel())] }; return View(model); @@ -47,15 +45,18 @@ public async Task Load(string name, int level, CancellationToken var model = new LoadViewModel { Theme = string.Empty, - Option = _mapper.Map( + Option = ( await _dungeonService.GetDungeonOptionByNameAsync(name, _currentUserService.GetUserIdAsInt(), - cancellationToken) ?? throw new ServiceException(Error.NotFound)), - Themes = (await _optionService.ListOptionsAsync(OptionKey.Theme, cancellationToken)) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value, Selected = true }) + cancellationToken) ?? throw new ServiceException(Error.NotFound)).ToViewModel(), + Themes = + [ + .. (await _optionService.ListOptionsAsync(OptionKey.Theme, cancellationToken)).Select(om => + new SelectListItem { Text = om.Name, Value = om.Value, Selected = true }) + ] }; if (level != 0) - model.Option.Dungeons = model.Option.Dungeons.Where(dm => dm.Level == level); + model.Option.Dungeons = [.. model.Option.Dungeons.Where(dm => dm.Level == level)]; ViewData["ReturnUrl"] = Url.Action(nameof(Index)); return View(model); @@ -83,6 +84,7 @@ public IActionResult Rename(int id, string dungeonName) { Id = id, DungeonName = dungeonName, + NewDungeonName = string.Empty, UserId = _currentUserService.GetUserIdAsInt() }; ViewData["ReturnUrl"] = Url.Action(nameof(Index)); @@ -137,7 +139,7 @@ private async Task GetMonsterTypeAsync(DungeonOptionCreateViewModel mode { var monsterType = string.Empty; var monsters = await _optionService.ListOptionsAsync(OptionKey.MonsterType, cancellationToken); - if (model.MonsterType?.Length == monsters.Count()) + if (model.MonsterType?.Length == monsters.Length) { monsterType = "any"; } @@ -161,8 +163,8 @@ public async Task Create(DungeonOptionCreateViewModel model, Canc { try { - var optionModel = _mapper.Map(model); - optionModel.MonsterType = await GetMonsterTypeAsync(model, cancellationToken); + var optionModel = model.ToModel(); + optionModel = optionModel with { MonsterType = await GetMonsterTypeAsync(model, cancellationToken) }; var dungeon = await _dungeonService.CreateOrUpdateDungeonAsync(optionModel, model.AddDungeon, model.Level, cancellationToken); return Json(JsonSerializer.Serialize(dungeon)); @@ -179,20 +181,11 @@ public async Task Create(DungeonOptionCreateViewModel model, Canc public async Task Create(int optionId, CancellationToken cancellationToken) { - var model = new DungeonOptionCreateViewModel - { - DeadEnd = true, - Corridor = true, - ItemsRarity = 1, - UserId = _currentUserService.GetUserIdAsInt(), - TrapPercent = 15, - Level = 1 - }; - + var model = DungeonMapper.CreateDefaultDungeonOptionCreateViewModel(_currentUserService.GetUserIdAsInt()); if (optionId != 0) { var option = await _dungeonService.GetDungeonOptionAsync(optionId, cancellationToken); - model = _mapper.Map(option); + model = option.ToCreateViewModel(); model.AddDungeon = true; if (model.MonsterType is not null && model.MonsterType[0].Equals("any")) { @@ -208,31 +201,60 @@ public async Task Create(int optionId, CancellationToken cancella private async Task FillCreateModelDropDownsAsync(DungeonOptionCreateViewModel model, CancellationToken cancellationToken) { - var options = await _optionService.ListOptionsAsync(null, cancellationToken); - var optionModels = options.ToList(); - model.DungeonSizes = optionModels.Where(om => om.Key == OptionKey.Size) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }); - model.DungeonDifficulties = optionModels.Where(om => om.Key == OptionKey.Difficulty) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }); + var optionModels = await _optionService.ListOptionsAsync(null, cancellationToken); + model.DungeonSizes = + [ + .. optionModels.Where(om => om.Key == OptionKey.Size) + .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }) + ]; + model.DungeonDifficulties = + [ + .. optionModels.Where(om => om.Key == OptionKey.Difficulty) + .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }) + ]; model.PartyLevels = SelectListHelper.GenerateIntSelectList(1, 20); model.PartySizes = SelectListHelper.GenerateIntSelectList(1, 10); - model.TreasureValues = optionModels.Where(om => om.Key == OptionKey.TreasureValue) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }); - model.ItemsRarities = optionModels.Where(om => om.Key == OptionKey.ItemsRarity) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }); - model.RoomDensities = optionModels.Where(om => om.Key == OptionKey.RoomDensity) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }); - model.RoomSizes = optionModels.Where(om => om.Key == OptionKey.RoomSize) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }); - model.MonsterTypes = optionModels.Where(om => om.Key == OptionKey.MonsterType).Select(om => - new SelectListItem { Text = om.Name, Value = om.Value, Selected = true }); - model.TrapPercents = optionModels.Where(om => om.Key == OptionKey.TrapPercent).Select(om => - new SelectListItem { Text = om.Name, Value = om.Value, Selected = true }); + model.TreasureValues = + [ + .. optionModels.Where(om => om.Key == OptionKey.TreasureValue) + .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }) + ]; + model.ItemsRarities = + [ + .. optionModels.Where(om => om.Key == OptionKey.ItemsRarity) + .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }) + ]; + model.RoomDensities = + [ + .. optionModels.Where(om => om.Key == OptionKey.RoomDensity) + .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }) + ]; + model.RoomSizes = + [ + .. optionModels.Where(om => om.Key == OptionKey.RoomSize) + .Select(om => new SelectListItem { Text = om.Name, Value = om.Value }) + ]; + model.MonsterTypes = + [ + .. optionModels.Where(om => om.Key == OptionKey.MonsterType).Select(om => + new SelectListItem { Text = om.Name, Value = om.Value, Selected = true }) + ]; + model.TrapPercents = + [ + .. optionModels.Where(om => om.Key == OptionKey.TrapPercent).Select(om => + new SelectListItem { Text = om.Name, Value = om.Value, Selected = true }) + ]; model.DeadEnds = SelectListHelper.GetBool(); model.Corridors = SelectListHelper.GetBool(); - model.RoamingPercents = optionModels.Where(om => om.Key == OptionKey.RoamingPercent) - .Select(om => new SelectListItem { Text = om.Name, Value = om.Value, Selected = true }); - model.Themes = optionModels.Where(om => om.Key == OptionKey.Theme).Select(om => new SelectListItem - { Text = om.Name, Value = om.Value, Selected = true }); + model.RoamingPercents = + [ + .. optionModels.Where(om => om.Key == OptionKey.RoamingPercent).Select(om => new SelectListItem + { Text = om.Name, Value = om.Value, Selected = true }) + ]; + model.Themes = + [ + .. optionModels.Where(om => om.Key == OptionKey.Theme).Select(om => new SelectListItem + { Text = om.Name, Value = om.Value, Selected = true }) + ]; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Controllers/Web/EncounterController.cs b/src/Open5ETools.Web/Controllers/Web/EncounterController.cs index b722009..6414b8f 100644 --- a/src/Open5ETools.Web/Controllers/Web/EncounterController.cs +++ b/src/Open5ETools.Web/Controllers/Web/EncounterController.cs @@ -1,5 +1,4 @@ -using MapsterMapper; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Open5ETools.Core.Common.Enums.EG; @@ -7,7 +6,7 @@ using Open5ETools.Core.Common.Extensions; using Open5ETools.Core.Common.Helpers; using Open5ETools.Core.Common.Interfaces.Services.EG; -using Open5ETools.Core.Common.Models.EG; +using Open5ETools.Web.Mappers; using Open5ETools.Web.Models.Encounter; namespace Open5ETools.Web.Controllers.Web; @@ -15,10 +14,9 @@ namespace Open5ETools.Web.Controllers.Web; [Authorize] public class EncounterController( IEncounterService encounterService, - ILogger logger, - IMapper mapper) : Controller + ILogger logger +) : Controller { - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; private readonly IEncounterService _encounterService = encounterService; @@ -30,24 +28,33 @@ public async Task Index() PartyLevels = SelectListHelper.GenerateIntSelectList(1, 20), PartySize = 4, PartySizes = SelectListHelper.GenerateIntSelectList(1, 10), - Difficulties = (await _encounterService.GetEnumListAsync()) - .Select(k => new SelectListItem { Text = k.Key, Value = k.Value.ToString() }) - .AddFirstItem(), + Difficulties = + [ + .. (await _encounterService.GetEnumListAsync()) + .Select(k => new SelectListItem { Text = k.Key, Value = k.Value.ToString() }) + .AddFirstItem() + ], SelectedMonsterTypes = [.. Enum.GetValues()], - MonsterTypes = (await _encounterService.GetEnumListAsync()) + MonsterTypes = + [ + .. (await _encounterService.GetEnumListAsync()) .Select(k => new SelectListItem { Text = k.Key, Value = k.Value.ToString(), Selected = true - }), + }) + ], SelectedSizes = [.. Enum.GetValues()], - Sizes = (await _encounterService.GetEnumListAsync()) + Sizes = + [ + .. (await _encounterService.GetEnumListAsync()) .Select(k => new SelectListItem { Text = k.Key, Value = k.Value.ToString() }) + ] }; return View(model); } @@ -56,15 +63,11 @@ public async Task Index() [HttpPost] public async Task Generate(EncounterOptionViewModel optionModel) { - var option = _mapper.Map(optionModel); + var option = optionModel.ToModel(); try { - var encounters = await _encounterService.GenerateAsync(option); - var model = new EncounterViewModel - { - Details = encounters.Monsters.Select(_mapper.Map), - SumXp = encounters.SumXp - }; + var encounter = await _encounterService.GenerateAsync(option); + var model = encounter.ToViewModel(); return PartialView("_Details", model); } catch (Exception ex) @@ -73,14 +76,14 @@ public async Task Generate(EncounterOptionViewModel optionModel) title: ex.Message, detail: ex.LocalizedMessage(), statusCode: StatusCodes.Status500InternalServerError - ); + ); } } public async Task MonsterDetail(int id) { var monster = await _encounterService.GetMonsterByIdAsync(id); - var model = _mapper.Map(monster); + var model = monster.ToViewModel(); return PartialView("_MonsterDetail", model); } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Controllers/Web/HomeController.cs b/src/Open5ETools.Web/Controllers/Web/HomeController.cs index d9bb41b..590e40b 100644 --- a/src/Open5ETools.Web/Controllers/Web/HomeController.cs +++ b/src/Open5ETools.Web/Controllers/Web/HomeController.cs @@ -12,6 +12,7 @@ public IActionResult Index() { return RedirectToAction("Login", "Auth"); } + return View(); } diff --git a/src/Open5ETools.Web/Controllers/Web/ProfileController.cs b/src/Open5ETools.Web/Controllers/Web/ProfileController.cs index 71a7232..24b0edc 100644 --- a/src/Open5ETools.Web/Controllers/Web/ProfileController.cs +++ b/src/Open5ETools.Web/Controllers/Web/ProfileController.cs @@ -1,9 +1,8 @@ -using MapsterMapper; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Open5ETools.Core.Common.Interfaces.Services; -using Open5ETools.Core.Common.Models.Services; using Open5ETools.Web.Extensions; +using Open5ETools.Web.Mappers; using Open5ETools.Web.Models.Profile; namespace Open5ETools.Web.Controllers.Web; @@ -12,26 +11,28 @@ namespace Open5ETools.Web.Controllers.Web; public class ProfileController( IUserService userService, ICurrentUserService currentUserService, - IMapper mapper, ILogger logger) : Controller { private readonly IUserService _userService = userService; private readonly ICurrentUserService _currentUserService = currentUserService; - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; public async Task Index(CancellationToken cancellationToken) { var model = await _userService.GetAsync(_currentUserService.GetUserIdAsInt(), cancellationToken); - return View(_mapper.Map(model)); + return View(model.ToViewModel()); } - [HttpGet] public IActionResult ChangePassword() { ViewData["ReturnUrl"] = Url.Action(nameof(Index)); - return View(new ProfileChangePasswordModel()); + return View(new ProfileChangePasswordModel + { + CurrentPassword = string.Empty, + NewPassword = string.Empty, + ConfirmPassword = string.Empty + }); } [HttpPost] @@ -43,7 +44,7 @@ public async Task ChangePassword(ProfileChangePasswordModel model { try { - await _userService.ChangePasswordAsync(_mapper.Map(model), cancellationToken); + await _userService.ChangePasswordAsync(model.ToPasswordModel(), cancellationToken); return RedirectToAction("Index"); } catch (Exception ex) diff --git a/src/Open5ETools.Web/Controllers/Web/SpellController.cs b/src/Open5ETools.Web/Controllers/Web/SpellController.cs index c220927..a011f19 100644 --- a/src/Open5ETools.Web/Controllers/Web/SpellController.cs +++ b/src/Open5ETools.Web/Controllers/Web/SpellController.cs @@ -1,7 +1,7 @@ -using MapsterMapper; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Open5ETools.Core.Common.Interfaces.Services.SM; +using Open5ETools.Web.Mappers; using Open5ETools.Web.Models; using Open5ETools.Web.Models.Spell; @@ -10,10 +10,9 @@ namespace Open5ETools.Web.Controllers.Web; [Authorize] public class SpellController( ISpellService spellService, - ILogger logger, - IMapper mapper) : Controller + ILogger logger +) : Controller { - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; private readonly ISpellService _spellService = spellService; @@ -25,7 +24,7 @@ public async Task Index( int pageSize = 10) { var result = await _spellService.ListAsync(search); - var items = result.Select(_mapper.Map); + var items = result.Select(spell => spell.ToModel()); var model = new XPagedListViewModel(items, page, pageSize, search, sort, ascending); return View(model); } @@ -33,7 +32,6 @@ public async Task Index( public async Task Detail(int id) { var spell = await _spellService.GetAsync(id); - var model = _mapper.Map(spell); - return PartialView("_Details", model); + return PartialView("_Details", spell.ToModel()); } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Controllers/Web/UserController.cs b/src/Open5ETools.Web/Controllers/Web/UserController.cs index 533b8f9..52a6b0c 100644 --- a/src/Open5ETools.Web/Controllers/Web/UserController.cs +++ b/src/Open5ETools.Web/Controllers/Web/UserController.cs @@ -1,19 +1,17 @@ -using MapsterMapper; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Open5ETools.Core.Common.Interfaces.Services; -using Open5ETools.Core.Common.Models.Services; using Open5ETools.Core.Domain; using Open5ETools.Web.Extensions; +using Open5ETools.Web.Mappers; using Open5ETools.Web.Models.User; namespace Open5ETools.Web.Controllers.Web; [Authorize(Roles = Roles.Admin)] -public class UserController(IUserService userService, IMapper mapper, ILogger logger) : Controller +public class UserController(IUserService userService, ILogger logger) : Controller { private readonly IUserService _userService = userService; - private readonly IMapper _mapper = mapper; private readonly ILogger _logger = logger; public async Task Index() @@ -22,14 +20,23 @@ public async Task Index() return View(new UserListViewModel { - Details = list.Select(_mapper.Map) + Details = [.. list.Select(um => um.ToEditViewModel())] }); } [HttpGet] public IActionResult Create() { - return View(new UserCreateViewModel()); + return View(new UserCreateViewModel + { + Username = string.Empty, + Password = string.Empty, + ConfirmPassword = string.Empty, + FirstName = string.Empty, + LastName = string.Empty, + Email = string.Empty, + Role = string.Empty + }); } [HttpPost] @@ -40,7 +47,7 @@ public async Task Create(UserCreateViewModel model, CancellationT { try { - await _userService.CreateAsync(_mapper.Map(model), cancellationToken); + await _userService.CreateAsync(model.ToModel(), cancellationToken); return RedirectToAction("Index"); } catch (Exception ex) @@ -55,8 +62,8 @@ public async Task Create(UserCreateViewModel model, CancellationT [HttpGet] public async Task Edit(int id, CancellationToken cancellationToken) { - var model = _mapper.Map(await _userService.GetAsync(id, cancellationToken)); - return View(model); + var user = await _userService.GetAsync(id, cancellationToken); + return View(user.ToEditViewModel()); } [HttpPost] @@ -67,9 +74,7 @@ public async Task Edit(UserEditViewModel model, CancellationToken { try { - var user = new UserModel(); - _mapper.Map(model, user); - await _userService.UpdateAsync(user, cancellationToken); + await _userService.UpdateAsync(model.ToModel(), cancellationToken); return RedirectToAction("Index"); } catch (Exception ex) diff --git a/src/Open5ETools.Web/Mappers/DungeonMapper.cs b/src/Open5ETools.Web/Mappers/DungeonMapper.cs new file mode 100644 index 0000000..afedc4d --- /dev/null +++ b/src/Open5ETools.Web/Mappers/DungeonMapper.cs @@ -0,0 +1,142 @@ +using System.Globalization; +using Open5ETools.Core.Common.Models.DM.Services; +using Open5ETools.Web.Models.Dungeon; + +namespace Open5ETools.Web.Mappers; + +public static class DungeonMapper +{ + public static DungeonOptionViewModel ToViewModel(this DungeonOptionModel model) + { + return new DungeonOptionViewModel + { + DungeonName = model.DungeonName, + DungeonSize = model.DungeonSize, + DungeonDifficulty = model.DungeonDifficulty, + PartyLevel = model.PartyLevel, + PartySize = model.PartySize, + Corridor = model.Corridor, + DeadEnd = model.DeadEnd, + Dungeons = [.. model.Dungeons.Select(ToViewModel)], + ItemsRarity = model.ItemsRarity, + MonsterType = model.MonsterType, + RoamingPercent = model.RoamingPercent, + RoomDensity = model.RoomDensity, + RoomSize = model.RoomSize, + TrapPercent = model.TrapPercent, + TreasureValue = model.TreasureValue, + Id = model.Id, + Created = model.Created, + CreatedBy = model.CreatedBy, + LastModified = model.LastModified, + LastModifiedBy = model.LastModifiedBy, + Timestamp = model.Timestamp + }; + } + + private static DungeonViewModel ToViewModel(this DungeonModel model) + { + return new DungeonViewModel + { + DungeonTiles = model.DungeonTiles, + RoomDescription = model.RoomDescription, + TrapDescription = model.TrapDescription, + RoamingMonsterDescription = model.RoamingMonsterDescription ?? string.Empty, + DungeonOptionId = model.DungeonOptionId, + Level = model.Level, + Id = model.Id, + Created = model.Created, + CreatedBy = model.CreatedBy, + LastModified = model.LastModified, + LastModifiedBy = model.LastModifiedBy, + Timestamp = model.Timestamp + }; + } + + public static DungeonOptionCreateViewModel CreateDefaultDungeonOptionCreateViewModel(int userId) + { + return new DungeonOptionCreateViewModel + { + DungeonName = string.Empty, + DungeonSize = 0, + DungeonDifficulty = 0, + PartyLevel = 1, + PartySize = 4, + Corridor = true, + DeadEnd = true, + ItemsRarity = 1, + MonsterType = null, + RoamingPercent = 0, + RoomDensity = 0, + RoomSize = 0, + TrapPercent = 15, + TreasureValue = string.Empty, + Id = 0, + Created = DateTime.UtcNow, + CreatedBy = string.Empty, + LastModified = DateTime.UtcNow, + LastModifiedBy = string.Empty, + UserId = userId + }; + } + + public static DungeonOptionCreateViewModel ToCreateViewModel(this DungeonOptionModel model) + { + return new DungeonOptionCreateViewModel + { + DungeonName = model.DungeonName, + DungeonSize = model.DungeonSize, + DungeonDifficulty = model.DungeonDifficulty, + PartyLevel = model.PartyLevel, + PartySize = model.PartySize, + Corridor = model.Corridor, + DeadEnd = model.DeadEnd, + ItemsRarity = model.ItemsRarity, + MonsterType = model.MonsterType.Split(','), + RoamingPercent = model.RoamingPercent, + RoomDensity = model.RoomDensity, + RoomSize = model.RoomSize, + TrapPercent = model.TrapPercent, + TreasureValue = model.TreasureValue.ToString(CultureInfo.InvariantCulture), + Id = model.Id, + Created = model.Created, + CreatedBy = model.CreatedBy, + LastModified = model.LastModified, + LastModifiedBy = model.LastModifiedBy, + Timestamp = model.Timestamp, + UserId = model.UserId + }; + } + + public static DungeonOptionModel ToModel(this DungeonOptionCreateViewModel viewModel) + { + var monsterType = string.Empty; + if (viewModel.MonsterType is not null) + monsterType = string.Join(",", viewModel.MonsterType); + return new DungeonOptionModel + ( + viewModel.DungeonName, + viewModel.UserId, + viewModel.DungeonSize, + viewModel.DungeonDifficulty, + viewModel.PartyLevel, + viewModel.PartySize, + Convert.ToDouble(viewModel.TreasureValue, CultureInfo.InvariantCulture), + viewModel.ItemsRarity, + viewModel.RoomDensity, + viewModel.RoomSize, + monsterType, + viewModel.TrapPercent, + viewModel.DeadEnd, + viewModel.Corridor, + viewModel.RoamingPercent, + [], + viewModel.Id, + viewModel.Timestamp, + viewModel.CreatedBy, + viewModel.Created, + viewModel.LastModifiedBy, + viewModel.LastModified + ); + } +} \ No newline at end of file diff --git a/src/Open5ETools.Web/Mappers/EncounterMapper.cs b/src/Open5ETools.Web/Mappers/EncounterMapper.cs new file mode 100644 index 0000000..55b267b --- /dev/null +++ b/src/Open5ETools.Web/Mappers/EncounterMapper.cs @@ -0,0 +1,42 @@ +using Open5ETools.Core.Common.Models.EG; +using Open5ETools.Web.Models.Encounter; + +namespace Open5ETools.Web.Mappers; + +public static class EncounterMapper +{ + public static EncounterOption ToModel(this EncounterOptionViewModel model) + { + return new EncounterOption + ( + model.PartyLevel, + model.PartySize, + model.Difficulty, + model.SelectedMonsterTypes, + model.SelectedSizes, + model.Count + ); + } + + public static EncounterViewModel ToViewModel(this EncounterModel model) + { + return new EncounterViewModel + { + Monsters = [.. model.Monsters.Select(m => m.ToViewModel())] + }; + } + + public static MonsterViewModel ToViewModel(this MonsterModel monster) + { + return new MonsterViewModel + { + Monster = monster.JsonMonsterModel, + Id = monster.Id, + Timestamp = monster.Timestamp, + Created = monster.Created, + CreatedBy = monster.CreatedBy, + LastModified = monster.LastModified, + LastModifiedBy = monster.LastModifiedBy + }; + } +} \ No newline at end of file diff --git a/src/Open5ETools.Web/Mappers/ProfileMapper.cs b/src/Open5ETools.Web/Mappers/ProfileMapper.cs new file mode 100644 index 0000000..6deb48d --- /dev/null +++ b/src/Open5ETools.Web/Mappers/ProfileMapper.cs @@ -0,0 +1,34 @@ +using Open5ETools.Core.Common.Models.Services; +using Open5ETools.Web.Models.Profile; + +namespace Open5ETools.Web.Mappers; + +public static class ProfileMapper +{ + public static ProfileViewModel ToViewModel(this UserModel user) + { + return new ProfileViewModel + { + Username = user.Username, + FirstName = user.FirstName, + LastName = user.LastName, + Email = user.Email, + Id = user.Id, + Created = user.Created, + CreatedBy = user.CreatedBy, + LastModified = user.LastModified, + LastModifiedBy = user.LastModifiedBy, + Timestamp = user.Timestamp + }; + } + + public static ChangePasswordModel ToPasswordModel(this ProfileChangePasswordModel model) + { + return new ChangePasswordModel + ( + model.Id, + model.CurrentPassword, + model.NewPassword + ); + } +} \ No newline at end of file diff --git a/src/Open5ETools.Web/Mappers/SpellMapper.cs b/src/Open5ETools.Web/Mappers/SpellMapper.cs new file mode 100644 index 0000000..6327302 --- /dev/null +++ b/src/Open5ETools.Web/Mappers/SpellMapper.cs @@ -0,0 +1,39 @@ +using Open5ETools.Core.Common.Models.SM; +using Open5ETools.Web.Models.Spell; + +namespace Open5ETools.Web.Mappers; + +public static class SpellMapper +{ + public static SpellViewModel ToModel(this SpellModel spellModel) + { + return new SpellViewModel + { + Name = spellModel.Name, + Desc = spellModel.Desc, + HigherLevel = spellModel.HigherLevel, + Page = spellModel.Page, + Range = spellModel.Range, + Components = spellModel.Components, + Material = spellModel.Material, + Ritual = spellModel.Ritual, + Duration = spellModel.Duration, + Concentration = spellModel.Concentration, + CastingTime = spellModel.CastingTime, + Level = spellModel.Level, + School = spellModel.School, + Class = spellModel.Class, + Archetype = spellModel.Archetype, + Circles = spellModel.Circles, + Domains = spellModel.Domains, + Oaths = spellModel.Oaths, + Patrons = spellModel.Patrons, + Id = spellModel.Id, + Timestamp = spellModel.Timestamp, + CreatedBy = spellModel.CreatedBy, + Created = spellModel.Created, + LastModifiedBy = spellModel.LastModifiedBy, + LastModified = spellModel.LastModified + }; + } +} \ No newline at end of file diff --git a/src/Open5ETools.Web/Mappers/UserMapper.cs b/src/Open5ETools.Web/Mappers/UserMapper.cs new file mode 100644 index 0000000..42eeb09 --- /dev/null +++ b/src/Open5ETools.Web/Mappers/UserMapper.cs @@ -0,0 +1,66 @@ +using Open5ETools.Core.Common.Models.Services; +using Open5ETools.Web.Models.User; + +namespace Open5ETools.Web.Mappers; + +public static class UserMapper +{ + public static UserEditViewModel ToEditViewModel(this UserModel user) + { + return new UserEditViewModel + { + Username = user.Username, + Email = user.Email, + FirstName = user.FirstName, + LastName = user.LastName, + Role = user.Role, + IsDeleted = user.IsDeleted, + Created = user.Created, + CreatedBy = user.CreatedBy, + Id = user.Id, + LastModified = user.LastModified, + LastModifiedBy = user.LastModifiedBy, + Timestamp = user.Timestamp + }; + } + + public static UserModel ToModel(this UserCreateViewModel user) + { + return new UserModel + ( + user.Username, + user.FirstName, + user.LastName, + user.Email, + user.Password, + user.IsDeleted, + user.Role, + user.Id, + user.Timestamp, + user.CreatedBy, + user.Created, + user.LastModifiedBy, + user.LastModified + ); + } + + public static UserModel ToModel(this UserEditViewModel user) + { + return new UserModel + ( + user.Username, + user.FirstName, + user.LastName, + user.Email, + string.Empty, + user.IsDeleted, + user.Role, + user.Id, + user.Timestamp, + user.CreatedBy, + user.Created, + user.LastModifiedBy, + user.LastModified + ); + } +} \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Dungeon/DungeonListViewModel.cs b/src/Open5ETools.Web/Models/Dungeon/DungeonListViewModel.cs index a38a11d..e221f1b 100644 --- a/src/Open5ETools.Web/Models/Dungeon/DungeonListViewModel.cs +++ b/src/Open5ETools.Web/Models/Dungeon/DungeonListViewModel.cs @@ -2,5 +2,5 @@ public class DungeonListViewModel { - public IEnumerable List { get; set; } = []; + public required DungeonOptionViewModel[] List { get; init; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Dungeon/DungeonOptionCreateViewModel.cs b/src/Open5ETools.Web/Models/Dungeon/DungeonOptionCreateViewModel.cs index f8e5c7b..2ea52d3 100644 --- a/src/Open5ETools.Web/Models/Dungeon/DungeonOptionCreateViewModel.cs +++ b/src/Open5ETools.Web/Models/Dungeon/DungeonOptionCreateViewModel.cs @@ -8,63 +8,66 @@ public class DungeonOptionCreateViewModel : EditViewModel [Required] [StringLength(50, MinimumLength = 3)] [Display(ResourceType = typeof(Resources.Dungeon), Name = "Name")] - public string DungeonName { get; set; } = string.Empty; - [Required] - public int DungeonSize { get; set; } - [Required] - public int DungeonDifficulty { get; set; } - [Required] - public int PartyLevel { get; set; } - [Required] - public int PartySize { get; set; } - [Required] - public string TreasureValue { get; set; } = string.Empty; - [Required] - public int ItemsRarity { get; set; } - [Required] - public int RoomDensity { get; set; } - [Required] - public int RoomSize { get; set; } - [Required] - public string[]? MonsterType { get; set; } - [Required] - public int TrapPercent { get; set; } - [Required] - public bool DeadEnd { get; set; } - [Required] - public bool Corridor { get; set; } - [Required] - public int RoamingPercent { get; set; } + public required string DungeonName { get; set; } + + [Required] public required int DungeonSize { get; set; } + [Required] public required int DungeonDifficulty { get; set; } + [Required] public required int PartyLevel { get; set; } + [Required] public required int PartySize { get; set; } + [Required] public required string TreasureValue { get; set; } + [Required] public required int ItemsRarity { get; set; } + [Required] public required int RoomDensity { get; set; } + [Required] public required int RoomSize { get; set; } + [Required] public required string[]? MonsterType { get; set; } + [Required] public required int TrapPercent { get; set; } + [Required] public required bool DeadEnd { get; set; } + [Required] public required bool Corridor { get; set; } + [Required] public required int RoamingPercent { get; set; } public int Theme { get; set; } + [Display(ResourceType = typeof(Resources.Dungeon), Name = "DungeonSize")] - public IEnumerable DungeonSizes { get; set; } = []; + public SelectListItem[] DungeonSizes { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "DungeonDifficulty")] - public IEnumerable DungeonDifficulties { get; set; } = []; + public SelectListItem[] DungeonDifficulties { get; set; } = []; + [Display(ResourceType = typeof(Resources.Common), Name = "PartyLevel")] - public IEnumerable PartyLevels { get; set; } = []; + public SelectListItem[] PartyLevels { get; set; } = []; + [Display(ResourceType = typeof(Resources.Common), Name = "PartySize")] - public IEnumerable PartySizes { get; set; } = []; + public SelectListItem[] PartySizes { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "TreasureValue")] - public IEnumerable TreasureValues { get; set; } = []; + public SelectListItem[] TreasureValues { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "ItemsRarity")] - public IEnumerable ItemsRarities { get; set; } = []; + public SelectListItem[] ItemsRarities { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "RoomDensity")] - public IEnumerable RoomDensities { get; set; } = []; + public SelectListItem[] RoomDensities { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "RoomSize")] - public IEnumerable RoomSizes { get; set; } = []; + public SelectListItem[] RoomSizes { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "MonsterType")] - public IEnumerable MonsterTypes { get; set; } = []; + public SelectListItem[] MonsterTypes { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "TrapPercent")] - public IEnumerable TrapPercents { get; set; } = []; + public SelectListItem[] TrapPercents { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "DeadEnd")] - public IEnumerable DeadEnds { get; set; } = []; + public SelectListItem[] DeadEnds { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "Corridor")] - public IEnumerable Corridors { get; set; } = []; + public SelectListItem[] Corridors { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "RoamingPercent")] - public IEnumerable RoamingPercents { get; set; } = []; + public SelectListItem[] RoamingPercents { get; set; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "Theme")] - public IEnumerable Themes { get; set; } = []; - public int UserId { get; set; } + public SelectListItem[] Themes { get; set; } = []; + + public int UserId { get; init; } public bool AddDungeon { get; set; } public int Level { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Dungeon/DungeonOptionViewModel.cs b/src/Open5ETools.Web/Models/Dungeon/DungeonOptionViewModel.cs index 41d3b11..16f68ac 100644 --- a/src/Open5ETools.Web/Models/Dungeon/DungeonOptionViewModel.cs +++ b/src/Open5ETools.Web/Models/Dungeon/DungeonOptionViewModel.cs @@ -6,32 +6,20 @@ public class DungeonOptionViewModel : EditViewModel { [Required] [StringLength(50, MinimumLength = 3)] - public string DungeonName { get; set; } = string.Empty; - [Required] - public int DungeonSize { get; set; } - [Required] - public int DungeonDifficulty { get; set; } - [Required] - public int PartyLevel { get; set; } - [Required] - public int PartySize { get; set; } - [Required] - public double TreasureValue { get; set; } - [Required] - public int ItemsRarity { get; set; } - [Required] - public int RoomDensity { get; set; } - [Required] - public int RoomSize { get; set; } - [Required] - public string MonsterType { get; set; } = string.Empty; - [Required] - public int TrapPercent { get; set; } - [Required] - public bool DeadEnd { get; set; } - [Required] - public bool Corridor { get; set; } - [Required] - public int RoamingPercent { get; set; } - public IEnumerable Dungeons { get; set; } = []; + public required string DungeonName { get; set; } + + [Required] public required int DungeonSize { get; set; } + [Required] public required int DungeonDifficulty { get; set; } + [Required] public required int PartyLevel { get; set; } + [Required] public required int PartySize { get; set; } + [Required] public required double TreasureValue { get; set; } + [Required] public required int ItemsRarity { get; set; } + [Required] public required int RoomDensity { get; set; } + [Required] public required int RoomSize { get; set; } + [Required] public required string MonsterType { get; set; } + [Required] public required int TrapPercent { get; set; } + [Required] public required bool DeadEnd { get; set; } + [Required] public required bool Corridor { get; set; } + [Required] public required int RoamingPercent { get; set; } + public required DungeonViewModel[] Dungeons { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Dungeon/DungeonRenameViewModel.cs b/src/Open5ETools.Web/Models/Dungeon/DungeonRenameViewModel.cs index b3e3fcc..96fd3cf 100644 --- a/src/Open5ETools.Web/Models/Dungeon/DungeonRenameViewModel.cs +++ b/src/Open5ETools.Web/Models/Dungeon/DungeonRenameViewModel.cs @@ -4,13 +4,13 @@ namespace Open5ETools.Web.Models.Dungeon; public class DungeonRenameViewModel : EditViewModel { - public int UserId { get; set; } + public int UserId { get; init; } [Required] [StringLength(50, MinimumLength = 3)] [Display(ResourceType = typeof(Resources.Dungeon), Name = "Name")] - public string DungeonName { get; set; } = string.Empty; + public required string DungeonName { get; set; } [Required] [StringLength(50, MinimumLength = 3)] [Display(ResourceType = typeof(Resources.Dungeon), Name = "NewName")] - public string NewDungeonName { get; set; } = string.Empty; + public required string NewDungeonName { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Dungeon/DungeonViewModel.cs b/src/Open5ETools.Web/Models/Dungeon/DungeonViewModel.cs index 4f1162c..7cae38c 100644 --- a/src/Open5ETools.Web/Models/Dungeon/DungeonViewModel.cs +++ b/src/Open5ETools.Web/Models/Dungeon/DungeonViewModel.cs @@ -5,11 +5,11 @@ namespace Open5ETools.Web.Models.Dungeon; public class DungeonViewModel : EditViewModel { [Required] - public string DungeonTiles { get; set; } = string.Empty; + public required string DungeonTiles { get; init; } [Required] - public string RoomDescription { get; set; } = string.Empty; - public string TrapDescription { get; set; } = string.Empty; - public string RoamingMonsterDescription { get; set; } = string.Empty; + public required string RoomDescription { get; init; } + public required string TrapDescription { get; init; } + public required string RoamingMonsterDescription { get; init; } public int DungeonOptionId { get; set; } - public int Level { get; set; } + public int Level { get; init; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Dungeon/LoadViewModel.cs b/src/Open5ETools.Web/Models/Dungeon/LoadViewModel.cs index 03b188e..178412d 100644 --- a/src/Open5ETools.Web/Models/Dungeon/LoadViewModel.cs +++ b/src/Open5ETools.Web/Models/Dungeon/LoadViewModel.cs @@ -5,10 +5,12 @@ namespace Open5ETools.Web.Models.Dungeon; public class LoadViewModel { - public DungeonOptionViewModel Option { get; set; } = new(); - public string Theme { get; set; } = string.Empty; + public required DungeonOptionViewModel Option { get; set; } + public required string Theme { get; set; } + [Display(ResourceType = typeof(Resources.Dungeon), Name = "Theme")] - public IEnumerable Themes { get; set; } = []; + public SelectListItem[] Themes { get; init; } = []; + [Display(ResourceType = typeof(Resources.Dungeon), Name = "GeneratePlainMap")] public bool GeneratePlainMap { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Encounter/EncounterOptionViewModel.cs b/src/Open5ETools.Web/Models/Encounter/EncounterOptionViewModel.cs index c1198fe..a481aef 100644 --- a/src/Open5ETools.Web/Models/Encounter/EncounterOptionViewModel.cs +++ b/src/Open5ETools.Web/Models/Encounter/EncounterOptionViewModel.cs @@ -1,26 +1,35 @@ using Microsoft.AspNetCore.Mvc.Rendering; using Open5ETools.Core.Common.Enums.EG; using System.ComponentModel.DataAnnotations; + namespace Open5ETools.Web.Models.Encounter; public class EncounterOptionViewModel : EditViewModel { - [Required] - public int PartyLevel { get; set; } + [Required] public int PartyLevel { get; set; } + [Display(ResourceType = typeof(Resources.Common), Name = "PartyLevel")] - public IEnumerable PartyLevels { get; set; } = []; - [Required] - public int PartySize { get; set; } + public SelectListItem[] PartyLevels { get; init; } = []; + + [Required] public int PartySize { get; set; } + [Display(ResourceType = typeof(Resources.Common), Name = "PartySize")] - public IEnumerable PartySizes { get; set; } = []; + public SelectListItem[] PartySizes { get; init; } = []; + public Difficulty? Difficulty { get; set; } + [Display(ResourceType = typeof(Resources.Common), Name = "Difficulty")] - public IEnumerable Difficulties { get; set; } = []; - public List SelectedMonsterTypes { get; set; } = []; + public SelectListItem[] Difficulties { get; init; } = []; + + public MonsterType[] SelectedMonsterTypes { get; set; } = []; + [Display(ResourceType = typeof(Resources.Encounter), Name = "MonsterType")] - public IEnumerable MonsterTypes { get; set; } = []; - public List SelectedSizes { get; set; } = []; + public SelectListItem[] MonsterTypes { get; init; } = []; + + public Size[] SelectedSizes { get; set; } = []; + [Display(ResourceType = typeof(Resources.Common), Name = "Size")] - public IEnumerable Sizes { get; set; } = []; + public SelectListItem[] Sizes { get; init; } = []; + public int Count { get; set; } = 9; } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Encounter/EncounterViewModel.cs b/src/Open5ETools.Web/Models/Encounter/EncounterViewModel.cs index 46abe65..618dfd1 100644 --- a/src/Open5ETools.Web/Models/Encounter/EncounterViewModel.cs +++ b/src/Open5ETools.Web/Models/Encounter/EncounterViewModel.cs @@ -2,6 +2,6 @@ namespace Open5ETools.Web.Models.Encounter; public class EncounterViewModel { - public int SumXp { get; set; } - public IEnumerable Details { get; set; } = []; + public int SumXp => Monsters.Sum(m => m.Monster.Xp); + public MonsterViewModel[] Monsters { get; init; } = []; } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Encounter/JsonMonsterViewModel.cs b/src/Open5ETools.Web/Models/Encounter/JsonMonsterViewModel.cs deleted file mode 100644 index d0fbcc9..0000000 --- a/src/Open5ETools.Web/Models/Encounter/JsonMonsterViewModel.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Open5ETools.Core.Common.Models.Json; - -namespace Open5ETools.Web.Models.Encounter; - -public class JsonMonsterViewModel -{ - public int Xp { get; set; } - public int Count { get; set; } - public string Name { get; set; } = string.Empty; - public string Type { get; set; } = string.Empty; - public string Difficulty { get; set; } = string.Empty; - public string ChallengeRating { get; set; } = string.Empty; - public string Size { get; set; } = string.Empty; - public string Alignment { get; set; } = string.Empty; - public int Hp { get; set; } - public int Ac { get; set; } - public string HitDice { get; set; } = string.Empty; - public string Speed { get; set; } = string.Empty; - public string? Senses { get; set; } - public string? Languages { get; set; } - public int Strength { get; set; } - public int Dexterity { get; set; } - public int Constitution { get; set; } - public int Intelligence { get; set; } - public int Wisdom { get; set; } - public int Charisma { get; set; } - public int StrengthSave { get; set; } - public int DexteritySave { get; set; } - public int ConstitutionSave { get; set; } - public int IntelligenceSave { get; set; } - public int WisdomSave { get; set; } - public int CharismaSave { get; set; } - public int History { get; set; } - public int Perception { get; set; } - public string? DamageVulnerabilities { get; set; } - public string? DamageResistances { get; set; } - public string? DamageImmunities { get; set; } - public string? ConditionImmunities { get; set; } - public List SpecialAbilities { get; set; } = []; - public List Actions { get; set; } = []; - public List LegendaryActions { get; set; } = []; - public List Reactions { get; set; } = []; -} \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Encounter/MonsterViewModel.cs b/src/Open5ETools.Web/Models/Encounter/MonsterViewModel.cs index 6dd1aae..e2b0e93 100644 --- a/src/Open5ETools.Web/Models/Encounter/MonsterViewModel.cs +++ b/src/Open5ETools.Web/Models/Encounter/MonsterViewModel.cs @@ -1,7 +1,8 @@ +using Open5ETools.Core.Common.Models.EG; namespace Open5ETools.Web.Models.Encounter; public class MonsterViewModel : EditViewModel { - public JsonMonsterViewModel JsonMonsterModel { get; set; } = new(); + public required JsonMonsterModel Monster { get; init; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Home/ErrorViewModel.cs b/src/Open5ETools.Web/Models/Home/ErrorViewModel.cs index ee09918..e1225b3 100644 --- a/src/Open5ETools.Web/Models/Home/ErrorViewModel.cs +++ b/src/Open5ETools.Web/Models/Home/ErrorViewModel.cs @@ -1,9 +1,8 @@ - namespace Open5ETools.Web.Models.Home; public class ErrorViewModel { - public string RequestId { get; set; } = string.Empty; + public required string RequestId { get; init; } public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Profile/ProfileChangePasswordModel.cs b/src/Open5ETools.Web/Models/Profile/ProfileChangePasswordModel.cs index 7dd8c4a..96f346a 100644 --- a/src/Open5ETools.Web/Models/Profile/ProfileChangePasswordModel.cs +++ b/src/Open5ETools.Web/Models/Profile/ProfileChangePasswordModel.cs @@ -7,14 +7,17 @@ public class ProfileChangePasswordModel : EditViewModel [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [DataType(DataType.Password)] [Display(ResourceType = typeof(Resources.User), Name = "CurrentPassword")] - public string CurrentPassword { get; set; } = string.Empty; + public required string CurrentPassword { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [DataType(DataType.Password)] [Display(ResourceType = typeof(Resources.User), Name = "Password")] - public string NewPassword { get; set; } = string.Empty; + public required string NewPassword { get; set; } + [Required(ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(Resources.Error))] - [Compare("NewPassword", ErrorMessageResourceName = "ConfirmPassword", ErrorMessageResourceType = typeof(Resources.Error))] + [Compare("NewPassword", ErrorMessageResourceName = "ConfirmPassword", + ErrorMessageResourceType = typeof(Resources.Error))] [DataType(DataType.Password)] [Display(ResourceType = typeof(Resources.User), Name = "ConfirmPassword")] - public string ConfirmPassword { get; set; } = string.Empty; + public required string ConfirmPassword { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Profile/ProfileViewModel.cs b/src/Open5ETools.Web/Models/Profile/ProfileViewModel.cs index e5c69c4..d9d8db6 100644 --- a/src/Open5ETools.Web/Models/Profile/ProfileViewModel.cs +++ b/src/Open5ETools.Web/Models/Profile/ProfileViewModel.cs @@ -2,8 +2,8 @@ public class ProfileViewModel : EditViewModel { - public string Username { get; set; } = string.Empty; - public string FirstName { get; set; } = string.Empty; - public string LastName { get; set; } = string.Empty; - public string Email { get; set; } = string.Empty; + public required string Username { get; init; } + public required string FirstName { get; init; } + public required string LastName { get; init; } + public required string Email { get; init; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/Spell/SpellViewModel.cs b/src/Open5ETools.Web/Models/Spell/SpellViewModel.cs index ee86996..dece83d 100644 --- a/src/Open5ETools.Web/Models/Spell/SpellViewModel.cs +++ b/src/Open5ETools.Web/Models/Spell/SpellViewModel.cs @@ -4,41 +4,23 @@ namespace Open5ETools.Web.Models.Spell; public class SpellViewModel : EditViewModel { - public string Name { get; set; } = string.Empty; - - public string Desc { get; set; } = string.Empty; - - public string? HigherLevel { get; set; } - - public string Page { get; set; } = string.Empty; - - public string Range { get; set; } = string.Empty; - - public string Components { get; set; } = string.Empty; - - public string? Material { get; set; } - - public bool Ritual { get; set; } - - public string? Duration { get; set; } - - public bool Concentration { get; set; } - - public string CastingTime { get; set; } = string.Empty; - - public string Level { get; set; } = string.Empty; - - public School School { get; set; } - - public string Class { get; set; } = string.Empty; - - public string? Archetype { get; set; } - - public string? Circles { get; set; } - - public string? Domains { get; set; } - - public string? Oaths { get; set; } - - public string? Patrons { get; set; } + public required string Name { get; init; } + public required string Desc { get; init; } + public required string CastingTime { get; init; } + public required string Level { get; init; } + public required string Class { get; init; } + public required string Page { get; init; } + public required string Range { get; init; } + public required string Components { get; init; } + public required School School { get; init; } + public bool Ritual { get; init; } + public bool Concentration { get; init; } + public string? Duration { get; init; } + public string? Material { get; init; } + public string? HigherLevel { get; init; } + public string? Archetype { get; init; } + public string? Circles { get; init; } + public string? Domains { get; init; } + public string? Oaths { get; init; } + public string? Patrons { get; init; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/User/UserCreateViewModel.cs b/src/Open5ETools.Web/Models/User/UserCreateViewModel.cs index 4711c1f..2bac5bb 100644 --- a/src/Open5ETools.Web/Models/User/UserCreateViewModel.cs +++ b/src/Open5ETools.Web/Models/User/UserCreateViewModel.cs @@ -6,27 +6,35 @@ public class UserCreateViewModel : EditViewModel { [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "Username")] - public string Username { get; set; } = string.Empty; + public required string Username { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [DataType(DataType.Password)] [Display(ResourceType = typeof(Resources.User), Name = "Password")] - public string Password { get; set; } = string.Empty; + public required string Password { get; set; } + [Required(ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(Resources.Error))] - [Compare("Password", ErrorMessageResourceName = "ConfirmPassword", ErrorMessageResourceType = typeof(Resources.Error))] + [Compare("Password", ErrorMessageResourceName = "ConfirmPassword", + ErrorMessageResourceType = typeof(Resources.Error))] [DataType(DataType.Password)] [Display(ResourceType = typeof(Resources.User), Name = "ConfirmPassword")] - public string ConfirmPassword { get; set; } = string.Empty; + public required string ConfirmPassword { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "FirstName")] - public string FirstName { get; set; } = string.Empty; + public required string FirstName { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "LastName")] - public string LastName { get; set; } = string.Empty; + public required string LastName { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "Email")] - public string Email { get; set; } = string.Empty; + public required string Email { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "Role")] - public string Role { get; set; } = string.Empty; + public required string Role { get; set; } + public bool IsDeleted { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/User/UserEditViewModel.cs b/src/Open5ETools.Web/Models/User/UserEditViewModel.cs index a31e1e5..7377eef 100644 --- a/src/Open5ETools.Web/Models/User/UserEditViewModel.cs +++ b/src/Open5ETools.Web/Models/User/UserEditViewModel.cs @@ -4,18 +4,23 @@ namespace Open5ETools.Web.Models.User; public class UserEditViewModel : EditViewModel { - public string Username { get; set; } = string.Empty; + public required string Username { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "FirstName")] - public string FirstName { get; set; } = string.Empty; + public required string FirstName { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "LastName")] - public string LastName { get; set; } = string.Empty; + public required string LastName { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "Email")] - public string Email { get; set; } = string.Empty; + public required string Email { get; set; } + [Required(ErrorMessageResourceType = typeof(Resources.Error), ErrorMessageResourceName = "RequiredValidation")] [Display(ResourceType = typeof(Resources.User), Name = "Role")] - public string Role { get; set; } = string.Empty; + public required string Role { get; set; } + public bool IsDeleted { get; set; } } \ No newline at end of file diff --git a/src/Open5ETools.Web/Models/User/UserListViewModel.cs b/src/Open5ETools.Web/Models/User/UserListViewModel.cs index 626bab6..d7f4337 100644 --- a/src/Open5ETools.Web/Models/User/UserListViewModel.cs +++ b/src/Open5ETools.Web/Models/User/UserListViewModel.cs @@ -2,5 +2,5 @@ public class UserListViewModel { - public IEnumerable Details { get; set; } = []; + public UserEditViewModel[] Details { get; init; } = []; } \ No newline at end of file diff --git a/src/Open5ETools.Web/Open5ETools.Web.csproj b/src/Open5ETools.Web/Open5ETools.Web.csproj index eaa3e3a..03d869b 100644 --- a/src/Open5ETools.Web/Open5ETools.Web.csproj +++ b/src/Open5ETools.Web/Open5ETools.Web.csproj @@ -2,7 +2,7 @@ true true - 1.0.6.0 + 1.0.7.0 diff --git a/src/Open5ETools.Web/Views/Encounter/_Details.cshtml b/src/Open5ETools.Web/Views/Encounter/_Details.cshtml index 8406c71..fafd718 100644 --- a/src/Open5ETools.Web/Views/Encounter/_Details.cshtml +++ b/src/Open5ETools.Web/Views/Encounter/_Details.cshtml @@ -1,28 +1,28 @@ @model Open5ETools.Web.Models.Encounter.EncounterViewModel
- @foreach (var monster in Model.Details) + @foreach (var monster in Model.Monsters) {
- @monster.JsonMonsterModel.Count x @monster.JsonMonsterModel.Name + @monster.Monster.Count x @monster.Monster.Name
-
@monster.JsonMonsterModel.Type - (@monster.JsonMonsterModel.Size)
+
@monster.Monster.Type + (@monster.Monster.Size)

- @Resources.Common.Difficulty: @monster.JsonMonsterModel.Difficulty + @Resources.Common.Difficulty: @monster.Monster.Difficulty

- (@monster.JsonMonsterModel.Xp @Resources.Encounter.Xp) + (@monster.Monster.Xp @Resources.Encounter.Xp)

diff --git a/src/Open5ETools.Web/Views/Encounter/_MonsterDetail.cshtml b/src/Open5ETools.Web/Views/Encounter/_MonsterDetail.cshtml index 2250cdf..935e600 100644 --- a/src/Open5ETools.Web/Views/Encounter/_MonsterDetail.cshtml +++ b/src/Open5ETools.Web/Views/Encounter/_MonsterDetail.cshtml @@ -9,31 +9,31 @@
- +
- +
- +
- +
- +
- +
@@ -42,10 +42,10 @@
+ value="@Model.Monster.Strength (@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Strength))">
+ class="input-group-text saving-throw">@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Strength)
@@ -53,10 +53,10 @@
+ value="@Model.Monster.Dexterity (@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Dexterity))">
+ class="input-group-text saving-throw">@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Dexterity)
@@ -64,10 +64,10 @@
+ value="@Model.Monster.Constitution (@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Constitution))">
+ class="input-group-text saving-throw">@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Constitution)
@@ -77,10 +77,10 @@ + value="@Model.Monster.Intelligence (@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Intelligence))">
+ class="input-group-text saving-throw">@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Intelligence)
@@ -88,10 +88,10 @@
+ value="@Model.Monster.Wisdom (@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Wisdom))">
+ class="input-group-text saving-throw">@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Wisdom)
@@ -99,10 +99,10 @@
+ value="@Model.Monster.Charisma (@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Charisma))">
+ class="input-group-text saving-throw">@Open5ETools.Core.Common.Helpers.AbilityHelper.CalcMod(@Model.Monster.Charisma)
@@ -111,16 +111,16 @@
- +
- +
-@if (Model.JsonMonsterModel.Actions is not null && Model.JsonMonsterModel.Actions.Count > 0) +@if (Model.Monster.Actions.Length > 0) {

@Resources.Encounter.Actions

@@ -135,7 +135,7 @@ - @foreach (var action in @Model.JsonMonsterModel.Actions) + @foreach (var action in @Model.Monster.Actions) { @action.Name @@ -156,7 +156,7 @@
} -@if (Model.JsonMonsterModel.Reactions is not null && Model.JsonMonsterModel.Reactions.Count > 0) +@if (Model.Monster.Reactions.Length > 0) {

@Resources.Encounter.Reactions

@@ -169,7 +169,7 @@ - @foreach (var reaction in @Model.JsonMonsterModel.Reactions) + @foreach (var reaction in @Model.Monster.Reactions) { @reaction.Name @@ -188,7 +188,7 @@
} -@if (Model.JsonMonsterModel.SpecialAbilities is not null && Model.JsonMonsterModel.SpecialAbilities.Count > 0) +@if (Model.Monster.SpecialAbilities.Length > 0) {

@Resources.Encounter.SpecialAbilities

@@ -202,7 +202,7 @@ - @foreach (var ability in @Model.JsonMonsterModel.SpecialAbilities) + @foreach (var ability in @Model.Monster.SpecialAbilities) { @ability.Name @@ -222,7 +222,7 @@
} -@if (Model.JsonMonsterModel.LegendaryActions is not null && Model.JsonMonsterModel.LegendaryActions.Count > 0) +@if (Model.Monster.LegendaryActions.Length > 0) {

@Resources.Encounter.LegendaryActions

@@ -236,7 +236,7 @@ - @foreach (var action in @Model.JsonMonsterModel.LegendaryActions) + @foreach (var action in @Model.Monster.LegendaryActions) { @action.Name diff --git a/tests/Open5ETools.Core.Tests/DungeonServiceTests/Create.cs b/tests/Open5ETools.Core.Tests/DungeonServiceTests/Create.cs index a8fc5b8..54962c9 100644 --- a/tests/Open5ETools.Core.Tests/DungeonServiceTests/Create.cs +++ b/tests/Open5ETools.Core.Tests/DungeonServiceTests/Create.cs @@ -13,27 +13,9 @@ public class Create(TestFixture fixture) : IClassFixture [Fact] public async Task CreateDungeonOptionAsync_WithOptionModel_ReturnsNewEntityId() { - var optionsModel = new DungeonOptionModel - { - DungeonName = "UT Dungeon 1", - Created = DateTime.UtcNow, - ItemsRarity = 1, - DeadEnd = true, - DungeonDifficulty = 1, - DungeonSize = 25, - MonsterType = "any", - PartyLevel = 4, - PartySize = 4, - TrapPercent = 20, - RoamingPercent = 0, - TreasureValue = 1, - RoomDensity = 10, - RoomSize = 20, - Corridor = false, - UserId = 1 - }; var result = - await _dungeonService.CreateDungeonOptionAsync(optionsModel, TestContext.Current.CancellationToken); + await _dungeonService.CreateDungeonOptionAsync(fixture.TestDungeonOptionModel, + TestContext.Current.CancellationToken); result.ShouldBeGreaterThan(0); } @@ -51,11 +33,7 @@ public async Task AddDungeonAsync_WithDungeonModel_ReturnsNewEntityId() [Fact] public async Task CreateOrUpdateDungeonAsync_WithInvalidModel_ReturnsServiceAggregateException() { - var optionsModel = new DungeonOptionModel - { - DungeonName = string.Empty, - UserId = 0 - }; + var optionsModel = fixture.TestDungeonOptionModel with { DungeonName = string.Empty, UserId = 0 }; var expectedErrors = new List { string.Format(Resources.Error.RequiredValidation, nameof(DungeonOptionModel.DungeonName)), @@ -79,27 +57,9 @@ await _dungeonService.CreateOrUpdateDungeonAsync(optionsModel, false, 1, [Fact] public async Task CreateOrUpdateDungeonAsync_WithValidNewModel_CreateOptionAndReturnsDungeonModel() { - var optionsModel = new DungeonOptionModel - { - DungeonName = "UT Dungeon 2", - Created = DateTime.UtcNow, - ItemsRarity = 1, - DeadEnd = true, - DungeonDifficulty = 1, - DungeonSize = 25, - MonsterType = "any", - PartyLevel = 4, - PartySize = 4, - TrapPercent = 20, - RoamingPercent = 0, - TreasureValue = 1, - RoomDensity = 10, - RoomSize = 20, - Corridor = false, - UserId = 1 - }; + var optionModel = fixture.TestDungeonOptionModel with { DungeonName = "UT Dungeon 2" }; var result = - await _dungeonService.CreateOrUpdateDungeonAsync(optionsModel, false, 1, + await _dungeonService.CreateOrUpdateDungeonAsync(optionModel, false, 1, TestContext.Current.CancellationToken); result.ShouldNotBeNull(); result.RoamingMonsterDescription.ShouldBe(Constants.Empty); @@ -116,12 +76,12 @@ public async Task .First(); var currentDungeonCount = (await _dungeonService.ListUserDungeonsByNameAsync(existingDungeonOption.DungeonName, userId, - TestContext.Current.CancellationToken)).Count(); + TestContext.Current.CancellationToken)).Length; var result = await _dungeonService.CreateOrUpdateDungeonAsync(existingDungeonOption, true, levelNumber, TestContext.Current.CancellationToken); var newDungeonCount = (await _dungeonService.ListUserDungeonsByNameAsync(existingDungeonOption.DungeonName, userId, - TestContext.Current.CancellationToken)).Count(); + TestContext.Current.CancellationToken)).Length; result.ShouldNotBeNull(); result.Level.ShouldBe(levelNumber); newDungeonCount.ShouldBeGreaterThan(currentDungeonCount); diff --git a/tests/Open5ETools.Core.Tests/DungeonServiceTests/Generate.cs b/tests/Open5ETools.Core.Tests/DungeonServiceTests/Generate.cs index 1a27787..0a83f1d 100644 --- a/tests/Open5ETools.Core.Tests/DungeonServiceTests/Generate.cs +++ b/tests/Open5ETools.Core.Tests/DungeonServiceTests/Generate.cs @@ -1,5 +1,6 @@ using Open5ETools.Core.Common.Interfaces.Services.DM; using Open5ETools.Core.Common.Models.DM.Services; +using Open5ETools.Infrastructure.Data; using Shouldly; namespace Open5ETools.Core.Tests.DungeonServiceTests; @@ -12,24 +13,30 @@ public class Generate(TestFixture fixture) : IClassFixture public async Task GenerateDungeonAsync_WithValidOptionModel_ReturnsDungeonModel() { var result = await _dungeonService.GenerateDungeonAsync(new DungeonOptionModel - { - DungeonName = "UT Dungeon", - Created = DateTime.UtcNow, - ItemsRarity = 1, - DeadEnd = true, - DungeonDifficulty = 1, - DungeonSize = 25, - MonsterType = "any", - PartyLevel = 4, - PartySize = 4, - TrapPercent = 20, - RoamingPercent = 0, - TreasureValue = 1, - RoomDensity = 10, - RoomSize = 20, - Corridor = false, - UserId = 1 - }, TestContext.Current.CancellationToken); + ( + "UT Dungeon", + AppDbContextInitializer.TestAdminUserId, + 25, + 1, + 4, + 4, + 1, + 1, + 10, + 20, + "any", + 20, + true, + false, + 0, + [], + 1, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ), TestContext.Current.CancellationToken); result.DungeonTiles.ShouldNotBeNull(); } diff --git a/tests/Open5ETools.Core.Tests/DungeonServiceTests/Update.cs b/tests/Open5ETools.Core.Tests/DungeonServiceTests/Update.cs index 3e3aa15..af670fd 100644 --- a/tests/Open5ETools.Core.Tests/DungeonServiceTests/Update.cs +++ b/tests/Open5ETools.Core.Tests/DungeonServiceTests/Update.cs @@ -13,10 +13,13 @@ public async Task UpdateDungeonAsync_WithValidDungeonModel_UpdatesExistingDungeo { const int dungeonId = 4; var oldDungeon = await _dungeonService.GetDungeonAsync(dungeonId, TestContext.Current.CancellationToken); - oldDungeon.DungeonTiles = Constants.Empty; - oldDungeon.TrapDescription = Constants.Empty; - oldDungeon.RoomDescription = Constants.Empty; - oldDungeon.RoamingMonsterDescription = Constants.Empty; + oldDungeon = oldDungeon with + { + DungeonTiles = Constants.Empty, + TrapDescription = Constants.Empty, + RoomDescription = Constants.Empty, + RoamingMonsterDescription = Constants.Empty + }; await _dungeonService.UpdateDungeonAsync(oldDungeon, TestContext.Current.CancellationToken); var result = await _dungeonService.GetDungeonAsync(dungeonId, TestContext.Current.CancellationToken); result.ShouldNotBeNull(); diff --git a/tests/Open5ETools.Core.Tests/EncounterServiceTests/EncounterOptionData.cs b/tests/Open5ETools.Core.Tests/EncounterServiceTests/EncounterOptionData.cs index bd54c26..7f0de7d 100644 --- a/tests/Open5ETools.Core.Tests/EncounterServiceTests/EncounterOptionData.cs +++ b/tests/Open5ETools.Core.Tests/EncounterServiceTests/EncounterOptionData.cs @@ -8,49 +8,53 @@ public static class EncounterOptionData public static TheoryData Data => [ new EncounterOption - { - PartyLevel = 4, - PartySize = 3, - MonsterTypes = [MonsterType.Aberration], - Sizes = [Size.Small, Size.Medium], - Count = 1 - }, + ( + 4, + 3, + null, + [MonsterType.Aberration], + [Size.Small, Size.Medium], + 1 + ), new EncounterOption - { - PartyLevel = 3, - PartySize = 4, - MonsterTypes = [MonsterType.Ooze, MonsterType.Fey], - Sizes = [Size.Tiny, Size.Small, Size.Medium], - Count = 6 - }, + ( + 3, + 4, + null, + [MonsterType.Ooze, MonsterType.Fey], + [Size.Tiny, Size.Small, Size.Medium], + 6 + ), new EncounterOption - { - PartyLevel = 4, - PartySize = 5, - MonsterTypes = [MonsterType.Elemental, MonsterType.Giant, MonsterType.Fiend], - Sizes = [Size.Small, Size.Medium, Size.Large], - Count = 3 - }, + ( + 4, + 5, + null, + [MonsterType.Elemental, MonsterType.Giant, MonsterType.Fiend], + [Size.Small, Size.Medium, Size.Large], + 3 + ), new EncounterOption - { - PartyLevel = 8, - PartySize = 4, - MonsterTypes = [MonsterType.Beast, MonsterType.Humanoid, MonsterType.Celestial, MonsterType.Dragon], - Sizes = [Size.Medium, Size.Large, Size.Huge], - Count = 5 - }, + ( + 8, + 4, + null, + [MonsterType.Beast, MonsterType.Humanoid, MonsterType.Celestial, MonsterType.Dragon], + [Size.Medium, Size.Large, Size.Huge], + 5 + ), new EncounterOption - { - PartyLevel = 12, - PartySize = 3, - MonsterTypes = + ( + 12, + 3, + null, [ MonsterType.SwarmOfTinyBeasts, MonsterType.Undead, MonsterType.Construct, MonsterType.Plant, MonsterType.Monstrosity ], - Sizes = [Size.Medium, Size.Large, Size.Huge, Size.Gargantuan], - Count = 2 - } + [Size.Medium, Size.Large, Size.Huge, Size.Gargantuan], + 2 + ) ]; public static TheoryData FilterWithDifficultyData => diff --git a/tests/Open5ETools.Core.Tests/EncounterServiceTests/Generate.cs b/tests/Open5ETools.Core.Tests/EncounterServiceTests/Generate.cs index f906127..91a3cf2 100644 --- a/tests/Open5ETools.Core.Tests/EncounterServiceTests/Generate.cs +++ b/tests/Open5ETools.Core.Tests/EncounterServiceTests/Generate.cs @@ -17,7 +17,7 @@ public async Task GenerateAsync_WithDifferentOptions_CanGenerateEncounters(Encou { var result = await _encounterService.GenerateAsync(option); result.ShouldNotBeNull(); - result.Monsters.Count.ShouldBe(option.Count); + result.Monsters.Length.ShouldBe(option.Count); } [Theory] @@ -40,29 +40,30 @@ public async Task GenerateAsync_WithDifferentOptions_CanFilterEncounters(Encount public async Task CanFilterWithDifficulty(Difficulty difficulty, int partyLevel, int partySize) { var option = new EncounterOption - { - PartyLevel = partyLevel, - MonsterTypes = [MonsterType.Beast, MonsterType.Humanoid, MonsterType.SwarmOfTinyBeasts], - PartySize = partySize, - Difficulty = difficulty - }; + ( + partyLevel, + partySize, + difficulty, + [MonsterType.Beast, MonsterType.Humanoid, MonsterType.SwarmOfTinyBeasts], + [] + ); var encounterModel = await _encounterService.GenerateAsync(option); encounterModel.ShouldNotBeNull(); encounterModel.Monsters.ShouldNotBeNull(); - encounterModel.Monsters.TrueForAll(e => e.JsonMonsterModel.Difficulty.Equals(difficulty.ToString())) - .ShouldBeTrue(); + encounterModel.Monsters.ShouldAllBe(m => m.JsonMonsterModel.Difficulty.Equals(difficulty.ToString())); } [Fact] public async Task CanThrowException() { var option = new EncounterOption - { - PartyLevel = 1, - PartySize = 1, - MonsterTypes = [MonsterType.Dragon], - Difficulty = Difficulty.Easy - }; + ( + 1, + 1, + Difficulty.Easy, + [MonsterType.Dragon], + [] + ); await Should.ThrowAsync(async () => { await _encounterService.GenerateAsync(option); }); } } \ No newline at end of file diff --git a/tests/Open5ETools.Core.Tests/HelperTests/SelectList.cs b/tests/Open5ETools.Core.Tests/HelperTests/SelectList.cs new file mode 100644 index 0000000..21b1bf4 --- /dev/null +++ b/tests/Open5ETools.Core.Tests/HelperTests/SelectList.cs @@ -0,0 +1,18 @@ +using Open5ETools.Core.Common.Helpers; +using Shouldly; + +namespace Open5ETools.Core.Tests.HelperTests; + +public class SelectList +{ + [Theory] + [InlineData(1, 12, 12)] + [InlineData(10, 20, 11)] + [InlineData(132, 242, 111)] + [InlineData(0, 256, 257)] + public void GenerateIntSelectList_ReturnsCorrectAmount(int from, int to, int expectedCount) + { + var count = SelectListHelper.GenerateIntSelectList(from, to).Length; + count.ShouldBe(expectedCount); + } +} \ No newline at end of file diff --git a/tests/Open5ETools.Core.Tests/TestEnvironment.cs b/tests/Open5ETools.Core.Tests/TestEnvironment.cs index c297d08..307c7f5 100644 --- a/tests/Open5ETools.Core.Tests/TestEnvironment.cs +++ b/tests/Open5ETools.Core.Tests/TestEnvironment.cs @@ -53,23 +53,30 @@ public IDungeon GetDungeon(DungeonOptionModel? optionModel = null) { var dungeon = GetService(); optionModel ??= new DungeonOptionModel - { - DungeonName = "UT Dungeon", - Created = DateTime.UtcNow, - ItemsRarity = 1, - DeadEnd = true, - DungeonDifficulty = 1, - DungeonSize = 25, - MonsterType = "any", - PartyLevel = 4, - PartySize = 4, - TrapPercent = 20, - RoamingPercent = 0, - TreasureValue = 1, - RoomDensity = 10, - RoomSize = 20, - Corridor = false - }; + ( + "UT Dungeon", + AppDbContextInitializer.TestAdminUserId, + 25, + 1, + 4, + 4, + 1, + 1, + 10, + 20, + "any", + 20, + true, + false, + 0, + [], + 1, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); dungeon.Init(optionModel); return dungeon; @@ -79,23 +86,30 @@ public IDungeonNoCorridor GetNcDungeon(DungeonOptionModel? optionModel = null) { var dungeonNoCorridor = GetService(); optionModel ??= new DungeonOptionModel - { - DungeonName = "UT Dungeon", - Created = DateTime.UtcNow, - ItemsRarity = 1, - DeadEnd = true, - DungeonDifficulty = 1, - DungeonSize = 15, - MonsterType = "any", - PartyLevel = 4, - PartySize = 4, - TrapPercent = 20, - RoamingPercent = 0, - TreasureValue = 1, - RoomDensity = 10, - RoomSize = 15, - Corridor = false - }; + ( + "UT Dungeon", + AppDbContextInitializer.TestAdminUserId, + 15, + 1, + 4, + 4, + 1, + 1, + 10, + 15, + "any", + 20, + true, + false, + 0, + [], + 1, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); dungeonNoCorridor.Init(optionModel); return dungeonNoCorridor; diff --git a/tests/Open5ETools.Core.Tests/TestFixture.cs b/tests/Open5ETools.Core.Tests/TestFixture.cs index bbe0fb8..8efff51 100644 --- a/tests/Open5ETools.Core.Tests/TestFixture.cs +++ b/tests/Open5ETools.Core.Tests/TestFixture.cs @@ -6,6 +6,8 @@ using Open5ETools.Core.Common.Interfaces.Services.DM.Generator; using Open5ETools.Core.Common.Interfaces.Services.EG; using Open5ETools.Core.Common.Interfaces.Services.SM; +using Open5ETools.Core.Common.Models.DM.Services; +using Open5ETools.Infrastructure.Data; namespace Open5ETools.Core.Tests; @@ -22,6 +24,32 @@ public class TestFixture : IDisposable private readonly TestEnvironment _env = new(); private bool _disposedValue; + public readonly DungeonOptionModel TestDungeonOptionModel = new + ( + "UT Dungeon 1", + AppDbContextInitializer.TestAdminUserId, + 25, + 1, + 4, + 4, + 1, + 1, + 10, + 20, + "any", + 20, + true, + false, + 0, + [], + 1, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); + public TestFixture() { DungeonService = _env.GetService(); diff --git a/tests/Open5ETools.Core.Tests/UserServiceTests/ChangePassword.cs b/tests/Open5ETools.Core.Tests/UserServiceTests/ChangePassword.cs index 53ad7f7..41444dd 100644 --- a/tests/Open5ETools.Core.Tests/UserServiceTests/ChangePassword.cs +++ b/tests/Open5ETools.Core.Tests/UserServiceTests/ChangePassword.cs @@ -19,11 +19,11 @@ public class ChangePassword(TestFixture fixture) : IClassFixture public async Task ChangePasswordAsync_WithValidInput_ChangesPassword() { var model = new ChangePasswordModel - { - Id = AppDbContextInitializer.TestUserId, - CurrentPassword = _config.Value.DefaultUserPassword, - NewPassword = Password - }; + ( + AppDbContextInitializer.TestUserId, + _config.Value.DefaultUserPassword, + Password + ); var oldUserModel = await _userService.GetAsync(model.Id, TestContext.Current.CancellationToken); var act = async () => { await _userService.ChangePasswordAsync(model, TestContext.Current.CancellationToken); }; @@ -37,20 +37,23 @@ public static TheoryData GetModelsWithErrors() return [ (new ChangePasswordModel - { - NewPassword = "length" - }, Error.PasswordLength), + ( + AppDbContextInitializer.TestUserId, + Password, + "length" + ), Error.PasswordLength), (new ChangePasswordModel - { - NewPassword = Password, - Id = AppDbContextInitializer.TestNotExistingUserId, - }, Error.NotFound), + ( + AppDbContextInitializer.TestNotExistingUserId, + string.Empty, + Password + ), Error.NotFound), (new ChangePasswordModel - { - NewPassword = Password, - Id = AppDbContextInitializer.TestUserId, - CurrentPassword = "wrong" - }, Error.PasswordMissMatch) + ( + AppDbContextInitializer.TestUserId, + "wrong", + Password + ), Error.PasswordMissMatch) ]; } diff --git a/tests/Open5ETools.Core.Tests/UserServiceTests/Create.cs b/tests/Open5ETools.Core.Tests/UserServiceTests/Create.cs index 89e9cbc..ad183eb 100644 --- a/tests/Open5ETools.Core.Tests/UserServiceTests/Create.cs +++ b/tests/Open5ETools.Core.Tests/UserServiceTests/Create.cs @@ -16,14 +16,21 @@ public class Create(TestFixture fixture) : IClassFixture public async Task CreateAsync_WithValidModel_CreatesUser() { var model = new UserModel - { - Username = "ddd", - Password = "asdasdada+mnn!", - Email = "dasd@test.com", - FirstName = "John", - LastName = "Doe", - Role = nameof(Role.Admin) - }; + ( + "ddd", + "John", + "Doe", + "dasd@test.com", + "asdasdada+mnn!", + false, + nameof(Role.Admin), + 0, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); var result = await _userService.CreateAsync(model, cancellationToken: TestContext.Current.CancellationToken); result.ShouldBeGreaterThan(AppDbContextInitializer.TestDeletedUserId); } @@ -31,7 +38,22 @@ public async Task CreateAsync_WithValidModel_CreatesUser() [Fact] public async Task CreateAsync_WithInValidModel_ThrowsServiceAggregateException() { - var model = new UserModel(); + var model = new UserModel + ( + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + false, + string.Empty, + 0, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); var expectedErrors = new List { string.Format(Error.RequiredValidation, nameof(model.Username)), diff --git a/tests/Open5ETools.Core.Tests/UserServiceTests/Update.cs b/tests/Open5ETools.Core.Tests/UserServiceTests/Update.cs index e9e8802..1059977 100644 --- a/tests/Open5ETools.Core.Tests/UserServiceTests/Update.cs +++ b/tests/Open5ETools.Core.Tests/UserServiceTests/Update.cs @@ -17,7 +17,7 @@ public async Task UpdateAsync_WithValidModel_UpdatesUser() { var adminUser = await _userService.GetAsync(AppDbContextInitializer.TestAdminUserId, cancellationToken: TestContext.Current.CancellationToken); - adminUser.FirstName = ModifiedText; + adminUser = adminUser with { FirstName = ModifiedText }; await _userService.UpdateAsync(adminUser, cancellationToken: TestContext.Current.CancellationToken); var result = await _userService.GetAsync(adminUser.Id, cancellationToken: TestContext.Current.CancellationToken); @@ -27,7 +27,22 @@ public async Task UpdateAsync_WithValidModel_UpdatesUser() [Fact] public async Task UpdateAsync_WithInValidModel_ThrowsServiceAggregateException() { - var model = new UserModel(); + var model = new UserModel + ( + string.Empty, + string.Empty, + string.Empty, + string.Empty, + string.Empty, + false, + string.Empty, + 0, + [], + string.Empty, + DateTime.UtcNow, + string.Empty, + DateTime.UtcNow + ); var expectedErrors = new List { string.Format(Error.RequiredValidation, nameof(model.FirstName)),