From 9f10301ee3f41ea4a089fa6779c650e4c752ecc2 Mon Sep 17 00:00:00 2001 From: ronelm2000 Date: Tue, 8 Oct 2024 23:05:22 +0800 Subject: [PATCH] Adds "Import Deck" functionality --- .../ViewModels/Dialogs/ImportDeckViewModel.cs | 66 +++++++++++++++++++ .../{ => Dialogs}/ImportSetViewModel.cs | 10 +-- .../ViewModels/MainWindowViewModel.cs | 20 +++++- .../Views/ImportDeckDialog.axaml | 62 +++++++++++++++++ .../Views/ImportDeckDialog.axaml.cs | 29 ++++++++ .../Views/ImportSetDialog.axaml | 4 +- .../Views/ImportSetDialog.axaml.cs | 5 +- Montage.Weiss.Tools.GUI/Views/MainView.axaml | 5 +- MontageWeissTools/CLI/ExportVerb.cs | 8 ++- 9 files changed, 194 insertions(+), 15 deletions(-) create mode 100644 Montage.Weiss.Tools.GUI/ViewModels/Dialogs/ImportDeckViewModel.cs rename Montage.Weiss.Tools.GUI/ViewModels/{ => Dialogs}/ImportSetViewModel.cs (92%) create mode 100644 Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml create mode 100644 Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml.cs diff --git a/Montage.Weiss.Tools.GUI/ViewModels/Dialogs/ImportDeckViewModel.cs b/Montage.Weiss.Tools.GUI/ViewModels/Dialogs/ImportDeckViewModel.cs new file mode 100644 index 0000000..e364b7a --- /dev/null +++ b/Montage.Weiss.Tools.GUI/ViewModels/Dialogs/ImportDeckViewModel.cs @@ -0,0 +1,66 @@ +using Avalonia.Controls; +using CommunityToolkit.Mvvm.ComponentModel; +using Lamar; +using Montage.Weiss.Tools.CLI; +using Montage.Weiss.Tools.Entities; +using Montage.Weiss.Tools.GUI.Utilities; +using Serilog; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace Montage.Weiss.Tools.GUI.ViewModels.Dialogs; +public partial class ImportDeckViewModel : ViewModelBase +{ + private static readonly ILogger Log = Serilog.Log.ForContext(); + + [ObservableProperty] + private bool _isVisible; + + [ObservableProperty] + private Func _parent; + + [ObservableProperty] + private string deckUrl; + + public ImportDeckViewModel() + { + Parent = () => null; + IsVisible = Design.IsDesignMode; + DeckUrl = string.Empty; + } + + internal async Task ImportDeck() + { + if (Parent() is not MainWindowViewModel parentModel) + return; + if (parentModel.Container is not IContainer container) + return; + + var progressReporter = new ProgressReporter(Log, message => parentModel.Status = message); + + var command = new ExportVerb { Source = DeckUrl, NonInteractive = true, NoWarning = true }; + var deck = await command.Parse(container, progressReporter); + + parentModel.DeckName = deck.Name; + parentModel.DeckRemarks = deck.Remarks; + + var cacheList = deck.Ratios.Keys.Where(c => c.GetCachedImagePath() is null && c.EnglishSetType != EnglishSetType.Custom) + .DistinctBy(c => c.ReleaseID) + .Select(c => new CacheVerb { Language = (c.Language == CardLanguage.English ? "en" : "jp"), ReleaseIDorFullSerialID = c.ReleaseID }) + .ToList(); + + foreach (var cacheCommand in cacheList) + await cacheCommand.Run(container, progressReporter); + + parentModel.DeckRatioList.Clear(); + + foreach (var ratio in deck.Ratios) + parentModel.DeckRatioList.Add(new CardRatioViewModel(ratio.Key, ratio.Value)); + + parentModel.SortDeck(); + parentModel.UpdateDeckStats(); + + IsVisible = false; + } +} diff --git a/Montage.Weiss.Tools.GUI/ViewModels/ImportSetViewModel.cs b/Montage.Weiss.Tools.GUI/ViewModels/Dialogs/ImportSetViewModel.cs similarity index 92% rename from Montage.Weiss.Tools.GUI/ViewModels/ImportSetViewModel.cs rename to Montage.Weiss.Tools.GUI/ViewModels/Dialogs/ImportSetViewModel.cs index e20407b..b447121 100644 --- a/Montage.Weiss.Tools.GUI/ViewModels/ImportSetViewModel.cs +++ b/Montage.Weiss.Tools.GUI/ViewModels/Dialogs/ImportSetViewModel.cs @@ -12,7 +12,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Montage.Weiss.Tools.GUI.ViewModels; +namespace Montage.Weiss.Tools.GUI.ViewModels.Dialogs; public partial class ImportSetViewModel : ViewModelBase { private static readonly ILogger Log = Serilog.Log.ForContext(); @@ -21,14 +21,14 @@ public partial class ImportSetViewModel : ViewModelBase private bool _isVisible; [ObservableProperty] - private Func parent; + private Func _parent; [ObservableProperty] private string setUrl; public ImportSetViewModel() { - parent = () => null; + Parent = () => null; IsVisible = Design.IsDesignMode; SetUrl = string.Empty; } @@ -45,8 +45,6 @@ public async Task ParseSet(CancellationToken token = default) return; } - IsVisible = false; - var progressReporter = new ProgressReporter(Log, message => parentViewModel.Status = message); var command = new ParseVerb { URI = SetUrl @@ -55,6 +53,8 @@ public async Task ParseSet(CancellationToken token = default) await command.Run(container, progressReporter, token); + IsVisible = false; + void Command_SetParsed(object? sender, string setCode) { parentViewModel.SearchBarText = $"set:{setCode}"; diff --git a/Montage.Weiss.Tools.GUI/ViewModels/MainWindowViewModel.cs b/Montage.Weiss.Tools.GUI/ViewModels/MainWindowViewModel.cs index 63aaf71..025f497 100644 --- a/Montage.Weiss.Tools.GUI/ViewModels/MainWindowViewModel.cs +++ b/Montage.Weiss.Tools.GUI/ViewModels/MainWindowViewModel.cs @@ -26,6 +26,7 @@ using JasperFx.Core; using Montage.Weiss.Tools.GUI.Utilities; using Montage.Weiss.Tools.GUI.Views; +using Montage.Weiss.Tools.GUI.ViewModels.Dialogs; namespace Montage.Weiss.Tools.GUI.ViewModels; @@ -42,6 +43,7 @@ public partial class MainWindowViewModel : ViewModelBase public ObservableCollection DeckRatioList { get; set; } = []; public ReactiveCommand ImportSetCommand { get; init; } + public ReactiveCommand ImportDeckCommand { get; init; } public ReactiveCommand OpenLocalSetCommand { get; init; } public ReactiveCommand SaveDeckCommand { get; init; } public ReactiveCommand OpenDeckCommand { get; init; } @@ -67,6 +69,9 @@ public partial class MainWindowViewModel : ViewModelBase [ObservableProperty] public ImportSetViewModel _importSetDC; + [ObservableProperty] + public ImportDeckViewModel _importDeckDC; + public MainWindowViewModel() { Status = ""; @@ -102,16 +107,19 @@ public MainWindowViewModel() DeckRatioList.Add(new CardRatioViewModel()); DeckRatioList.Add(new CardRatioViewModel() { Image = new Uri("avares://wsm-gui/Assets/Samples/sample_card.jpg").Load() }); ImportSetDC = new ImportSetViewModel { IsVisible = false, Parent = () => null }; + ImportDeckDC = new ImportDeckViewModel { IsVisible = false, Parent = () => null }; } else { DatabaseViewList = []; ImportSetDC = new ImportSetViewModel { IsVisible = false, Parent = () => this }; + ImportDeckDC = new ImportDeckViewModel { IsVisible = false, Parent = () => this }; } log = Serilog.Log.Logger.ForContext(); ImportSetCommand = ReactiveCommand.CreateFromTask(ImportSet); + ImportDeckCommand = ReactiveCommand.CreateFromTask(ImportDeck); OpenLocalSetCommand = ReactiveCommand.CreateFromTask(OpenLocalSet); SaveDeckCommand = ReactiveCommand.CreateFromTask(SaveDeck); OpenDeckCommand = ReactiveCommand.CreateFromTask(OpenDeck); @@ -419,6 +427,14 @@ await Dispatcher.UIThread.InvokeAsync(() => */ } + internal async Task ImportDeck() + { + await Dispatcher.UIThread.InvokeAsync(() => + { + ImportDeckDC.IsVisible = true; + }); + } + internal async Task AddCard(WeissSchwarzCard card) { var existingRatio = DeckRatioList.Where(crv => crv.Card.Serial == card.Serial).FirstOrDefault(); @@ -465,7 +481,7 @@ internal async Task RemoveCard(WeissSchwarzCard card) await ValueTask.CompletedTask; } - private void SortDeck() + internal void SortDeck() { DeckRatioList.SortByDescending(crv => ( level: crv.Card.Level, @@ -482,7 +498,7 @@ private void SortDeck() }; } - private void UpdateDeckStats() + internal void UpdateDeckStats() { var totalCards = DeckRatioList.Select(crv => crv.Ratio).Sum(); var totalCharas = DeckRatioList.Where(crv => crv.Card.Type == CardType.Character) diff --git a/Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml b/Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml new file mode 100644 index 0000000..7a82f7c --- /dev/null +++ b/Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml.cs b/Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml.cs new file mode 100644 index 0000000..cac17f4 --- /dev/null +++ b/Montage.Weiss.Tools.GUI/Views/ImportDeckDialog.axaml.cs @@ -0,0 +1,29 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Montage.Weiss.Tools.GUI.ViewModels.Dialogs; +using System.Threading.Tasks; + +namespace Montage.Weiss.Tools.GUI.Views; + +public partial class ImportDeckDialog : UserControl +{ + public ImportDeckDialog() + { + InitializeComponent(); + } + + private void CancelButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + if (DataContext is not ImportDeckViewModel vm) + return; + vm.IsVisible = false; + } + + private void ParseButton_Click(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + { + if (DataContext is not ImportDeckViewModel vm) + return; + Task.Run(async () => await vm.ImportDeck()); + } +} \ No newline at end of file diff --git a/Montage.Weiss.Tools.GUI/Views/ImportSetDialog.axaml b/Montage.Weiss.Tools.GUI/Views/ImportSetDialog.axaml index 7b137ee..f0de9f5 100644 --- a/Montage.Weiss.Tools.GUI/Views/ImportSetDialog.axaml +++ b/Montage.Weiss.Tools.GUI/Views/ImportSetDialog.axaml @@ -2,7 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:vm="clr-namespace:Montage.Weiss.Tools.GUI.ViewModels;assembly=wsm-gui" + xmlns:vm="clr-namespace:Montage.Weiss.Tools.GUI.ViewModels.Dialogs;assembly=wsm-gui" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="100" x:Class="Montage.Weiss.Tools.GUI.Views.ImportSetDialog" x:DataType="vm:ImportSetViewModel" @@ -28,7 +28,7 @@ > - + - + @@ -155,6 +155,9 @@ + diff --git a/MontageWeissTools/CLI/ExportVerb.cs b/MontageWeissTools/CLI/ExportVerb.cs index c2ef9e5..2813582 100644 --- a/MontageWeissTools/CLI/ExportVerb.cs +++ b/MontageWeissTools/CLI/ExportVerb.cs @@ -65,13 +65,19 @@ public async Task Run(IContainer ioc, IProgress progress, Log.Information("Running..."); + var deck = await Parse(ioc, deckParserProgress, cancellationToken); + deck = await Run(ioc, deck); + } + + public async Task Parse(IContainer ioc, IProgress deckParserProgress, CancellationToken cancellationToken = default) + { var parser = await ioc.GetAllInstances>() .ToAsyncEnumerable() .WhereAwait(async parser => await parser.IsCompatible(Source)) .OrderByDescending(parser => parser.Priority) .FirstAsync(cancellationToken); var deck = await parser.Parse(Source, deckParserProgress, cancellationToken); - deck = await Run(ioc, deck); + return deck; } public async Task Run(IContainer ioc, WeissSchwarzDeck deck)