From d52ede4611ba4d8191112e603d790994965e3d83 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Sat, 1 Jan 2022 09:18:08 -0700 Subject: [PATCH] Wireup some remaining buttons and CPU displays --- Wabbajack.App.Wpf/Models/ResourceMonitor.cs | 60 ++++++++++++++++++- Wabbajack.App.Wpf/View Models/CPUDisplayVM.cs | 23 +------ .../View Models/Compilers/CompilerVM.cs | 3 +- .../View Models/Installers/InstallerVM.cs | 24 +++++++- .../View Models/Interfaces/ICpuStatusVM.cs | 5 +- .../InstallationCompleteView.xaml.cs | 13 ++-- .../Views/Installers/InstallationView.xaml.cs | 3 - Wabbajack.RateLimiter/IJob.cs | 2 + Wabbajack.RateLimiter/IResource.cs | 2 + Wabbajack.RateLimiter/Resource.cs | 5 +- 10 files changed, 97 insertions(+), 43 deletions(-) diff --git a/Wabbajack.App.Wpf/Models/ResourceMonitor.cs b/Wabbajack.App.Wpf/Models/ResourceMonitor.cs index ac373aab..ff2d7955 100644 --- a/Wabbajack.App.Wpf/Models/ResourceMonitor.cs +++ b/Wabbajack.App.Wpf/Models/ResourceMonitor.cs @@ -1,8 +1,12 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; +using System.Reactive.Disposables; using System.Reactive.Subjects; using System.Timers; +using DynamicData; +using DynamicData.Kernel; using Wabbajack.RateLimiter; namespace Wabbajack.Models; @@ -17,14 +21,31 @@ public class ResourceMonitor : IDisposable public IObservable<(string Name, long Throughput)[]> Updates => _updates; + private readonly SourceCache _tasks = new(x => x.ID); + public readonly ReadOnlyObservableCollection _tasksFiltered; + private readonly CompositeDisposable _compositeDisposable; + public ReadOnlyObservableCollection Tasks => _tasksFiltered; + + + + public ResourceMonitor(IEnumerable resources) { + _compositeDisposable = new CompositeDisposable(); _resources = resources.ToArray(); _timer = new Timer(); _timer.Interval = 1000; _timer.Elapsed += Elapsed; _timer.Enabled = true; + + _timer.DisposeWith(_compositeDisposable); + _prev = _resources.Select(x => (x.Name, (long)0)).ToArray(); + + _tasks.Connect() + .Bind(out _tasksFiltered) + .Subscribe() + .DisposeWith(_compositeDisposable); } private void Elapsed(object? sender, ElapsedEventArgs e) @@ -35,10 +56,47 @@ public class ResourceMonitor : IDisposable .ToArray(); _prev = current; _updates.OnNext(diff); + + _tasks.Edit(l => + { + var used = new HashSet(); + foreach (var resource in _resources) + { + foreach (var job in resource.Jobs) + { + used.Add(job.ID); + var tsk = l.Lookup(job.ID); + // Update + if (tsk != Optional.None) + { + var t = tsk.Value; + t.Msg = job.Description; + t.ProgressPercent = Percent.FactoryPutInRange(job.Current, (long)job.Size); + } + + // Create + else + { + var vm = new CPUDisplayVM + { + ID = job.ID, + StartTime = DateTime.Now, + Msg = job.Description, + ProgressPercent = Percent.FactoryPutInRange(job.Current, (long) job.Size) + }; + l.AddOrUpdate(vm); + } + } + } + + // Delete + foreach (var itm in l.Items.Where(v => !used.Contains(v.ID))) + l.Remove(itm); + }); } public void Dispose() { - _timer?.Dispose(); + _compositeDisposable.Dispose(); } } \ No newline at end of file diff --git a/Wabbajack.App.Wpf/View Models/CPUDisplayVM.cs b/Wabbajack.App.Wpf/View Models/CPUDisplayVM.cs index 03e09bd5..87371bc5 100644 --- a/Wabbajack.App.Wpf/View Models/CPUDisplayVM.cs +++ b/Wabbajack.App.Wpf/View Models/CPUDisplayVM.cs @@ -8,7 +8,7 @@ namespace Wabbajack public class CPUDisplayVM : ViewModel { [Reactive] - public int ID { get; set; } + public ulong ID { get; set; } [Reactive] public DateTime StartTime { get; set; } [Reactive] @@ -21,26 +21,5 @@ namespace Wabbajack public CPUDisplayVM() { } - - public CPUDisplayVM(IJob cpu) - { - AbsorbStatus(cpu); - } - - public void AbsorbStatus(IJob cpu) - { - /* TODO - bool starting = cpu.IsWorking && !IsWorking; - if (starting) - { - StartTime = DateTime.Now; - } - - ID = cpu.; - Msg = cpu.Msg; - ProgressPercent = cpu.ProgressPercent; - IsWorking = cpu.IsWorking; - */ - } } } diff --git a/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs b/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs index 9a41d0f0..d5a69548 100644 --- a/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs +++ b/Wabbajack.App.Wpf/View Models/Compilers/CompilerVM.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.ObjectModel; using System.Reactive; using System.Windows.Media.Imaging; using Microsoft.Extensions.Logging; @@ -36,7 +37,7 @@ namespace Wabbajack private readonly ObservableAsPropertyHelper _percentCompleted; public Percent PercentCompleted => _percentCompleted.Value; - public ObservableCollectionExtended StatusList { get; } = new ObservableCollectionExtended(); + public ReadOnlyObservableCollection StatusList { get; } public ObservableCollectionExtended Log => MWVM.Log; diff --git a/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs b/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs index cfb30e45..55892f80 100644 --- a/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs +++ b/Wabbajack.App.Wpf/View Models/Installers/InstallerVM.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.ObjectModel; using ReactiveUI; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -32,6 +33,7 @@ using Wabbajack.View_Models; using Wabbajack.Paths.IO; using Wabbajack.Services.OSIntegrated; using Wabbajack.Util; +using Configuration = Wabbajack.Networking.WabbajackClientApi.Configuration; using Consts = Wabbajack.Consts; using KnownFolders = Wabbajack.Paths.IO.KnownFolders; @@ -50,7 +52,7 @@ public enum InstallState Failure } -public class InstallerVM : BackNavigatingVM, IBackNavigatingVM +public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM { private const string LastLoadedModlist = "last-loaded-modlist"; private const string InstallSettingsPrefix = "install-settings-"; @@ -109,6 +111,9 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM private readonly SystemParametersConstructor _parametersConstructor; private readonly IGameLocator _gameLocator; private readonly LoggerProvider _loggerProvider; + private readonly ResourceMonitor _resourceMonitor; + private readonly Services.OSIntegrated.Configuration _configuration; + public ReadOnlyObservableCollection StatusList => _resourceMonitor.Tasks; [Reactive] public bool Installing { get; set; } @@ -130,16 +135,19 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM public ReactiveCommand BackCommand { get; } public InstallerVM(ILogger logger, DTOSerializer dtos, SettingsManager settingsManager, IServiceProvider serviceProvider, - SystemParametersConstructor parametersConstructor, IGameLocator gameLocator, LoggerProvider loggerProvider) : base(logger) + SystemParametersConstructor parametersConstructor, IGameLocator gameLocator, LoggerProvider loggerProvider, ResourceMonitor resourceMonitor, + Wabbajack.Services.OSIntegrated.Configuration configuration) : base(logger) { _logger = logger; + _configuration = configuration; LoggerProvider = loggerProvider; _settingsManager = settingsManager; _dtos = dtos; _serviceProvider = serviceProvider; _parametersConstructor = parametersConstructor; _gameLocator = gameLocator; - + _resourceMonitor = resourceMonitor; + Installer = new MO2InstallerVM(this); BackCommand = ReactiveCommand.Create(() => NavigateToGlobal.Send(NavigateToGlobal.ScreenType.ModeSelectionView)); @@ -164,6 +172,16 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM }; ModListLocation.Filters.Add(new CommonFileDialogFilter("Wabbajack Modlist", "*.wabbajack")); + OpenLogsCommand = ReactiveCommand.Create(() => + { + UIUtils.OpenFolder(_configuration.LogLocation); + }); + + GoToInstallCommand = ReactiveCommand.Create(() => + { + UIUtils.OpenFolder(Installer.Location.TargetPath); + }); + MessageBus.Current.Listen() .Subscribe(msg => LoadModlist(msg.Path, msg.Metadata).FireAndForget()) .DisposeWith(CompositeDisposable); diff --git a/Wabbajack.App.Wpf/View Models/Interfaces/ICpuStatusVM.cs b/Wabbajack.App.Wpf/View Models/Interfaces/ICpuStatusVM.cs index 25229688..3a149bae 100644 --- a/Wabbajack.App.Wpf/View Models/Interfaces/ICpuStatusVM.cs +++ b/Wabbajack.App.Wpf/View Models/Interfaces/ICpuStatusVM.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,8 +11,6 @@ namespace Wabbajack { public interface ICpuStatusVM : IReactiveObject { - ObservableCollectionExtended StatusList { get; } - MainWindowVM MWVM { get; } - (int CurrentCPUs, int DesiredCPUs) CurrentCpuCount { get; } + ReadOnlyObservableCollection StatusList { get; } } } diff --git a/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs b/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs index ef943f55..d2e70061 100644 --- a/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Installers/InstallationCompleteView.xaml.cs @@ -28,16 +28,13 @@ namespace Wabbajack InitializeComponent(); this.WhenActivated(dispose => { - this.WhenAny(x => x.ViewModel.Completed) - .Select(x => x?.Failed ?? false) + this.WhenAny(x => x.ViewModel.InstallState) + .Select(x => x == InstallState.Failure) .BindToStrict(this, x => x.AttentionBorder.Failure) .DisposeWith(dispose); - this.WhenAny(x => x.ViewModel.Completed) - .Select(x => x?.Failed ?? false) - .Select(failed => - { - return $"Installation {(failed ? "Failed" : "Complete")}"; - }) + this.WhenAny(x => x.ViewModel.InstallState) + .Select(x => x == InstallState.Failure) + .Select(failed => $"Installation {(failed ? "Failed" : "Complete")}") .BindToStrict(this, x => x.TitleText.Text) .DisposeWith(dispose); this.WhenAny(x => x.ViewModel.BackCommand) diff --git a/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml.cs b/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml.cs index c85b68cd..8864ced9 100644 --- a/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Installers/InstallationView.xaml.cs @@ -35,9 +35,6 @@ namespace Wabbajack .BindToStrict(this, view => view.InstallComplete.Visibility) .DisposeWith(disposables); - //ViewModel.WhenAnyValue(vm => vm.ModList.Name) - // .BindToStrict(this, view => view.Name) - ViewModel.WhenAnyValue(vm => vm.BackCommand) .BindToStrict(this, view => view.BackButton.Command) .DisposeWith(disposables); diff --git a/Wabbajack.RateLimiter/IJob.cs b/Wabbajack.RateLimiter/IJob.cs index e1568069..a87ac195 100644 --- a/Wabbajack.RateLimiter/IJob.cs +++ b/Wabbajack.RateLimiter/IJob.cs @@ -5,7 +5,9 @@ namespace Wabbajack.RateLimiter; public interface IJob { + public ulong ID { get; } public long? Size { get; set; } public long Current { get; } + public string Description { get; } public ValueTask Report(int processedSize, CancellationToken token); } \ No newline at end of file diff --git a/Wabbajack.RateLimiter/IResource.cs b/Wabbajack.RateLimiter/IResource.cs index b542f24a..af8fcc6c 100644 --- a/Wabbajack.RateLimiter/IResource.cs +++ b/Wabbajack.RateLimiter/IResource.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -9,6 +10,7 @@ public interface IResource string Name { get; } int MaxTasks { get; set; } long MaxThroughput { get; set; } + IEnumerable Jobs { get; } } public interface IResource : IResource diff --git a/Wabbajack.RateLimiter/Resource.cs b/Wabbajack.RateLimiter/Resource.cs index f22efa4d..f8ab1fd2 100644 --- a/Wabbajack.RateLimiter/Resource.cs +++ b/Wabbajack.RateLimiter/Resource.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.Versioning; @@ -13,10 +14,10 @@ public class Resource : IResource { private Channel _channel; private SemaphoreSlim _semaphore; - private ConcurrentDictionary> _tasks; + private readonly ConcurrentDictionary> _tasks; private ulong _nextId; private long _totalUsed; - + public IEnumerable Jobs => _tasks.Values; public Resource(string? humanName = null, int? maxTasks = null, long maxThroughput = long.MaxValue) {