// // DatabaseMigrator.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.EntityFrameworkCore; using NosSmooth.Data.Abstractions; using NosSmooth.Data.Database.Data; using Remora.Results; namespace NosSmooth.Data.Database; /// /// Migrates Nostale data into sqlite database. /// public class DatabaseMigrator { private readonly IDbContextFactory _dbContextFactory; /// /// Initializes a new instance of the class. /// /// The database context factory. public DatabaseMigrator(IDbContextFactory dbContextFactory) { _dbContextFactory = dbContextFactory; } /// /// Migrates the data into the database. /// /// The NosTale data. /// The cancellation token for cancelling the operation. /// A representing the result of the asynchronous operation. public async Task Migrate(NostaleData data, CancellationToken ct = default) { await using var context = await _dbContextFactory.CreateDbContextAsync(ct); var itemsResult = await MigrateItems(context, data); if (!itemsResult.IsSuccess) { return itemsResult; } var skillsResult = await MigrateSkills(context, data); if (!skillsResult.IsSuccess) { return skillsResult; } var monstersResult = await MigrateMonsters(context, data); if (!monstersResult.IsSuccess) { return monstersResult; } var mapsResult = await MigrateMaps(context, data); if (!mapsResult.IsSuccess) { return mapsResult; } var translationsResult = await MigrateTranslations(context, data); if (!translationsResult.IsSuccess) { return translationsResult; } await context.Database.EnsureDeletedAsync(ct); await context.Database.EnsureCreatedAsync(ct); try { await context.SaveChangesAsync(ct); } catch (Exception e) { return e; } return Result.FromSuccess(); } private Task MigrateTranslations(NostaleDataContext context, NostaleData data) { foreach (var languageTranslation in data.Translations) { foreach (var rootTranslations in languageTranslation.Value) { foreach (var translations in rootTranslations.Value) { var translation = new Translation { Key = translations.Key, Root = rootTranslations.Key, Language = languageTranslation.Key, Translated = translations.Value }; context.Add(translation); } } } return Task.FromResult(Result.FromSuccess()); } private Task MigrateItems(NostaleDataContext dbContext, NostaleData data) { foreach (var item in data.Items.Values) { var itemInfo = new ItemInfo { BagType = item.BagType, Data = item.Data, EquipmentSlot = item.EquipmentSlot, NameKey = item.Name.Key, SubType = item.SubType, Type = item.Type, VNum = item.VNum }; dbContext.Add(itemInfo); } return Task.FromResult(Result.FromSuccess()); } private Task MigrateSkills(NostaleDataContext dbContext, NostaleData data) { foreach (var skill in data.Skills.Values) { var skillInfo = new SkillInfo { CastId = skill.CastId, CastTime = skill.CastTime, Cooldown = skill.Cooldown, HitType = skill.HitType, MpCost = skill.MpCost, NameKey = skill.Name.Key, Range = skill.Range, SkillType = skill.SkillType, TargetType = skill.TargetType, VNum = skill.VNum, ZoneRange = skill.ZoneRange, AttackType = skill.AttackType, Element = skill.Element, UsesSecondaryWeapon = skill.UsesSecondaryWeapon, DashSpeed = skill.DashSpeed, ItemVNum = skill.ItemVNum, MorphOrUpgrade = skill.MorphOrUpgrade, Name = skill.Name, SpecialCost = skill.SpecialCost, Upgrade = skill.Upgrade }; dbContext.Add(skillInfo); } return Task.FromResult(Result.FromSuccess()); } private Task MigrateMonsters(NostaleDataContext dbContext, NostaleData data) { foreach (var monster in data.Monsters.Values) { var monsterInfo = new MonsterInfo { VNum = monster.VNum, NameKey = monster.Name.Key, Level = monster.Level, Range = monster.Range, NoticeRange = monster.NoticeRange, CastTime = monster.CastTime, Hostile = monster.Hostile, }; dbContext.Add(monsterInfo); } return Task.FromResult(Result.FromSuccess()); } private Task MigrateMaps(NostaleDataContext dbContext, NostaleData data) { foreach (var map in data.Maps.Values) { var grid = new byte[map.Height * map.Width]; for (short y = 0; y < map.Height; y++) { for (short x = 0; x < map.Width; x++) { grid[(y * map.Width) + x] = map.GetData(x, y); } } var mapInfo = new MapInfo { Height = map.Height, Width = map.Width, NameKey = map.Name.Key, Id = map.Id, Grid = grid }; dbContext.Add(mapInfo); } return Task.FromResult(Result.FromSuccess()); } }