From 370d3559dd8ffec2c185ecb1e9b2f10cdca786c5 Mon Sep 17 00:00:00 2001 From: Soryu MK-II Date: Wed, 10 Feb 2016 04:24:48 +0900 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=AF=8D=E6=B8=AF=E5=89=A9?= =?UTF-8?q?=E4=BD=99=E7=A9=BA=E9=97=B4=E4=BB=BB=E5=8A=A1=E6=A0=8F=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NotifyEx/Models/HomeportSpaceProcess.cs | 96 +++++++++++++++++++++++++ NotifyEx/Models/HpNotifier.cs | 9 +-- NotifyEx/Models/IWarningCounter.cs | 17 +++++ NotifyEx/Models/NotifyHost.cs | 59 ++++++++++++--- NotifyEx/Models/ShipNotifier.cs | 77 +++++++++++++++++--- NotifyEx/Models/SlotNotifier.cs | 82 ++++++++++++++++++--- NotifyEx/Models/SupplyNotifier.cs | 13 ++-- NotifyEx/NotifyEx.csproj | 2 + NotifyEx/Plugin.cs | 2 +- NotifyEx/Properties/AssemblyInfo.cs | 2 +- NotifyEx/ViewModels/ToolViewModel.cs | 16 ++--- 11 files changed, 323 insertions(+), 52 deletions(-) create mode 100644 NotifyEx/Models/HomeportSpaceProcess.cs create mode 100644 NotifyEx/Models/IWarningCounter.cs diff --git a/NotifyEx/Models/HomeportSpaceProcess.cs b/NotifyEx/Models/HomeportSpaceProcess.cs new file mode 100644 index 0000000..546b932 --- /dev/null +++ b/NotifyEx/Models/HomeportSpaceProcess.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Shell; +using Grabacr07.KanColleViewer.Composition; +using MetroTrilithon.Lifetime; +using MetroTrilithon.Mvvm; +using StatefulModel; + +namespace NotifyEx.Models +{ + [Export(typeof(IPlugin))] + [Export(typeof(ITaskbarProgress))] + [ExportMetadata("Guid", Guid)] + [ExportMetadata("Title", "HomeportSpaceProcessIndicator")] + [ExportMetadata("Description", "母港剩余空间(舰娘、装备)任务栏进度显示")] + [ExportMetadata("Version", "1.0")] + [ExportMetadata("Author", "@Yoctillion")] + public class HomeportSpaceProcess : IPlugin, ITaskbarProgress, IDisposableHolder + { + private const string Guid = "93B50362-76AA-4F2C-B6BE-8B1C7FEEA2A5"; + + private readonly MultipleDisposable _compositeDisposable = new MultipleDisposable(); + + public string Id { get; } = Guid + "-1"; + + public string DisplayName { get; } = "母港剩余空间"; + + public TaskbarItemProgressState State { get; private set; } + + public double Value { get; private set; } + + public event EventHandler Updated; + + + private readonly List _counters = new List(); + + public void Initialize() + { + this._counters.Add(ShipNotifier.Current); + this._counters.Add(SlotNotifier.Current); + + foreach (var counter in this._counters) + { + counter.Subscribe(nameof(counter.Enabled), this.Update).AddTo(this); + counter.Subscribe(nameof(counter.WarningCount), this.Update).AddTo(this); + counter.Subscribe(nameof(counter.Remain), this.Update).AddTo(this); + } + } + + private void Update() + { + // min means most dangerous(?) + var minValue = this._counters.Min(c => GetValue(c)); + + if (minValue == 0) + { + this.State = TaskbarItemProgressState.Error; + } + else if (minValue <= 1) + { + this.State = TaskbarItemProgressState.Paused; + } + else + { + this.State = TaskbarItemProgressState.Normal; + } + + this.Value = Math.Max(0, 1 - minValue / 2); + + this.Updated?.Invoke(this, EventArgs.Empty); + } + + private static double GetValue(IWarningCounter counter) + { + if (!counter.Enabled) return double.MaxValue; + + if (counter.WarningCount != 0) + { + return (double)counter.Remain / counter.WarningCount; + } + + // WarningCount == 0 && Remain == 0 + if (counter.Remain == 0) return 0; + + return double.MaxValue; + } + + public void Dispose() => this._compositeDisposable.Dispose(); + + public ICollection CompositeDisposable => this._compositeDisposable; + } +} diff --git a/NotifyEx/Models/HpNotifier.cs b/NotifyEx/Models/HpNotifier.cs index 33e1e2a..2218121 100644 --- a/NotifyEx/Models/HpNotifier.cs +++ b/NotifyEx/Models/HpNotifier.cs @@ -18,6 +18,8 @@ namespace NotifyEx.Models /// internal class HpNotifier { + public static HpNotifier Current = new HpNotifier(); + private static readonly Settings Settings = Settings.Default; public bool Enabled @@ -49,11 +51,10 @@ public bool EnabledShowDamageControl } } - public HpNotifier() + private HpNotifier() { - var host = NotifyHost.Current; - host.Register("/kcsapi/api_req_map/start", WarningType.Instance, s => this.CheckSituation()); - host.Register("/kcsapi/api_req_map/next", WarningType.Instance, s => this.CheckSituation()); + NotifyHost.Register("/kcsapi/api_req_map/start", WarningType.Instance, s => this.CheckSituation()); + NotifyHost.Register("/kcsapi/api_req_map/next", WarningType.Instance, s => this.CheckSituation()); } private string CheckSituation() diff --git a/NotifyEx/Models/IWarningCounter.cs b/NotifyEx/Models/IWarningCounter.cs new file mode 100644 index 0000000..ffe66b6 --- /dev/null +++ b/NotifyEx/Models/IWarningCounter.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Livet; + +namespace NotifyEx.Models +{ + public interface IWarningCounter : INotifyPropertyChanged + { + bool Enabled { get; } + uint WarningCount { get; } + uint Remain { get; } + } +} diff --git a/NotifyEx/Models/NotifyHost.cs b/NotifyEx/Models/NotifyHost.cs index bb040fb..b42ff37 100644 --- a/NotifyEx/Models/NotifyHost.cs +++ b/NotifyEx/Models/NotifyHost.cs @@ -14,9 +14,15 @@ public class NotifyHost { public static NotifyHost Current { get; internal set; } + public static event Action InstanceInitialized; + internal static void TryInitialize(Plugin notifier) { - if (Current == null) Current = new NotifyHost(notifier); + if (Current == null) + { + Current = new NotifyHost(notifier); + InstanceInitialized?.Invoke(); + } } @@ -67,13 +73,45 @@ public override int GetHashCode() private readonly Dictionary> _notifyProviders = new Dictionary>(); - /// - /// 注册通知操作 - /// - /// 监视的API - /// 通知类型 - /// return null => 不进行通知 - public void Register(string kcapi, INotifyType type, Func notifyProvider) + ///// + ///// 注册通知操作 + ///// + ///// 监视的API + ///// 通知类型 + ///// return null => 不进行通知 + //public void Register(string kcapi, INotifyType type, Func notifyProvider) + //{ + // var key = new NotifyTypeKey(kcapi, type); + + // Func action; + // if (this._notifyProviders.TryGetValue(key, out action)) + // { + // action += notifyProvider; + // this._notifyProviders[key] = action; + // } + // else + // { + // this._notifyProviders.Add(key, notifyProvider); + + // KanColleClient.Current.Proxy.ApiSessionSource + // .Where(s => s.Request.PathAndQuery == kcapi) + // .Subscribe(s => this.Notify(s, key)); + // } + //} + + public static void Register(string kcapi, INotifyType type, Func notifyProvider) + { + if (Current != null) + { + Current._Register(kcapi, type, notifyProvider); + } + else + { + InstanceInitialized += () => Current._Register(kcapi, type, notifyProvider); + } + } + + private void _Register(string kcapi, INotifyType type, Func notifyProvider) { var key = new NotifyTypeKey(kcapi, type); @@ -89,10 +127,11 @@ public void Register(string kcapi, INotifyType type, Func notif KanColleClient.Current.Proxy.ApiSessionSource .Where(s => s.Request.PathAndQuery == kcapi) - .Subscribe(s => this.Notify(s, key)); + .Subscribe(s => Current.Notify(s, key)); } } + private void Notify(Session session, NotifyTypeKey key) { var action = this._notifyProviders[key]; @@ -108,7 +147,7 @@ private void Notify(Session session, NotifyTypeKey key) public void Notify(string type, string header, string body) { - this._notifier.Notify(type, header, body); + Current?._notifier.Notify(type, header, body); } } } diff --git a/NotifyEx/Models/ShipNotifier.cs b/NotifyEx/Models/ShipNotifier.cs index 64b5814..f745ced 100644 --- a/NotifyEx/Models/ShipNotifier.cs +++ b/NotifyEx/Models/ShipNotifier.cs @@ -6,16 +6,21 @@ using System.Threading.Tasks; using Grabacr07.KanColleWrapper; using Livet; +using MetroTrilithon.Lifetime; +using MetroTrilithon.Mvvm; using NotifyEx.Models.NotifyType; using NotifyEx.Properties; +using StatefulModel; namespace NotifyEx.Models { /// /// 船位不足通知 /// - internal class ShipNotifier + internal class ShipNotifier : NotificationObject, IWarningCounter, IDisposableHolder { + public static ShipNotifier Current { get; } = new ShipNotifier(); + private static readonly Settings Settings = Settings.Default; public bool Enabled @@ -27,6 +32,7 @@ public bool Enabled { Settings.EnabledShipNotifier = value; Settings.Save(); + this.RaisePropertyChanged(); } } } @@ -40,27 +46,82 @@ public uint WarningCount { Settings.WarningShipCount = value; Settings.Save(); + this.RaisePropertyChanged(); } } } - public ShipNotifier() + private uint _remain = uint.MaxValue; + + public uint Remain { - NotifyHost.Current.Register("/kcsapi/api_get_member/mapinfo", WarningType.Instance, s => CheckReminding()); + get + { + return this._remain; + } + private set + { + if (this._remain != value) + { + this._remain = value; + this.RaisePropertyChanged(); + } + } } - private string CheckReminding() + private ShipNotifier() { - if (!Enabled) return null; + NotifyHost.Register("/kcsapi/api_get_member/mapinfo", WarningType.Instance, s => CheckReminding()); + + KanColleClient.Current + .Subscribe(nameof(KanColleClient.Current.IsStarted), this.Initialize, false) + .AddTo(this); + } + + private bool _initialized; + + private void Initialize() + { + if (this._initialized) return; + var homeport = KanColleClient.Current.Homeport; + if (homeport != null) + { + this._initialized = true; + + homeport.Organization + .Subscribe(nameof(homeport.Organization.Ships), this.UpdateRemainCount) + .AddTo(this); + homeport + .Subscribe(nameof(homeport.Admiral), this.UpdateRemainCount) + .AddTo(this); + } + } + + private void UpdateRemainCount() + { var port = KanColleClient.Current.Homeport; var maxShipCount = port.Admiral.MaxShipCount; var currentShipCount = port.Organization.Ships.Count; - var reminding = maxShipCount - currentShipCount; + this.Remain = (uint)(maxShipCount - currentShipCount); + } - if (reminding > WarningCount) return null; + private string CheckReminding() + { + if (!Enabled) return null; - return $"母港仅剩余 {reminding} 空位"; + if (this.Remain > WarningCount) return null; + + return this.Remain > 0 + ? $"母港仅剩余 {this.Remain} 空位" + : "舰娘保有数已满!"; } + + + private readonly MultipleDisposable _compositeDisposable = new MultipleDisposable(); + + public void Dispose() => this._compositeDisposable.Dispose(); + + public ICollection CompositeDisposable => this._compositeDisposable; } } diff --git a/NotifyEx/Models/SlotNotifier.cs b/NotifyEx/Models/SlotNotifier.cs index 23210be..4b9b9ce 100644 --- a/NotifyEx/Models/SlotNotifier.cs +++ b/NotifyEx/Models/SlotNotifier.cs @@ -6,13 +6,18 @@ using System.Threading.Tasks; using Grabacr07.KanColleWrapper; using Livet; +using MetroTrilithon.Lifetime; +using MetroTrilithon.Mvvm; using NotifyEx.Models.NotifyType; using NotifyEx.Properties; +using StatefulModel; namespace NotifyEx.Models { - internal class SlotNotifier + internal class SlotNotifier : NotificationObject, IWarningCounter, IDisposableHolder { + public static SlotNotifier Current { get; } = new SlotNotifier(); + private static readonly Settings Settings = Settings.Default; public bool Enabled @@ -24,6 +29,7 @@ public bool Enabled { Settings.EnabledSlotNotifier = value; Settings.Save(); + this.RaisePropertyChanged(); } } } @@ -37,27 +43,83 @@ public uint WarningCount { Settings.WarningSlotCount = value; Settings.Save(); + this.RaisePropertyChanged(); + } + } + } + + private uint _remain = uint.MaxValue; + + public uint Remain + { + get + { + return this._remain; + } + private set + { + if (this._remain != value) + { + this._remain = value; + this.RaisePropertyChanged(); } } } - public SlotNotifier() + + private SlotNotifier() { - NotifyHost.Current.Register("/kcsapi/api_get_member/mapinfo", WarningType.Instance, s => this.CheckReminding()); + NotifyHost.Register("/kcsapi/api_get_member/mapinfo", WarningType.Instance, s => this.CheckReminding()); + + KanColleClient.Current + .Subscribe(nameof(KanColleClient.Current.IsStarted), this.Initialize, false) + .AddTo(this); } - private string CheckReminding() + private bool _initialized; + + private void Initialize() { - if (!Enabled) return null; + if (this._initialized) return; + var homeport = KanColleClient.Current.Homeport; + if (homeport != null) + { + this._initialized = true; + + homeport.Itemyard + .Subscribe(nameof(homeport.Itemyard.SlotItemsCount), this.UpdateRemainCount) + .AddTo(this); + homeport.Admiral + .Subscribe(nameof(homeport.Admiral.MaxSlotItemCount), this.UpdateRemainCount) + .AddTo(this); + } + } + + private void UpdateRemainCount() + { var port = KanColleClient.Current.Homeport; - var max = port.Admiral.MaxSlotItemCount; - var current = port.Itemyard.SlotItemsCount; - var reminding = max - current; + var maxCount = port.Admiral.MaxSlotItemCount; + var currentCount = port.Itemyard.SlotItemsCount; + this.Remain = (uint)(maxCount - currentCount); + } - if (reminding > WarningCount) return null; + private string CheckReminding() + { + if (!Enabled) return null; - return $"装备仅剩余 {reminding} 空位"; + if (this.Remain > WarningCount) return null; + + return Remain > 0 + ? $"装备仅剩余 {this.Remain} 空位" + : "装备保有数已满!"; } + + + private readonly MultipleDisposable _compositeDisposable = new MultipleDisposable(); + + public void Dispose() => this._compositeDisposable.Dispose(); + + public ICollection CompositeDisposable => this._compositeDisposable; } } diff --git a/NotifyEx/Models/SupplyNotifier.cs b/NotifyEx/Models/SupplyNotifier.cs index 7507536..bbf5c2c 100644 --- a/NotifyEx/Models/SupplyNotifier.cs +++ b/NotifyEx/Models/SupplyNotifier.cs @@ -16,6 +16,8 @@ namespace NotifyEx.Models /// internal class SupplyNotifier { + public static SupplyNotifier Current { get; } = new SupplyNotifier(); + private static readonly Settings Settings = Settings.Default; public bool Enabled @@ -71,14 +73,13 @@ public bool EnabledExpendition } - internal SupplyNotifier() + private SupplyNotifier() { - var host = NotifyHost.Current; var type = WarningType.Instance; - host.Register("/kcsapi/api_get_member/mapinfo", type, s => this.CheckSortie()); - host.Register("/kcsapi/api_get_member/practice", type, s => this.CheckExercise()); - host.Register("/kcsapi/api_get_member/get_practice_enemyinfo", type, s => this.CheckExercise()); - host.Register("/kcsapi/api_get_member/mission", type, s => this.CheckExpendition()); + NotifyHost.Register("/kcsapi/api_get_member/mapinfo", type, s => this.CheckSortie()); + NotifyHost.Register("/kcsapi/api_get_member/practice", type, s => this.CheckExercise()); + NotifyHost.Register("/kcsapi/api_get_member/get_practice_enemyinfo", type, s => this.CheckExercise()); + NotifyHost.Register("/kcsapi/api_get_member/mission", type, s => this.CheckExpendition()); } private string CheckSortie() diff --git a/NotifyEx/NotifyEx.csproj b/NotifyEx/NotifyEx.csproj index 8f74463..3e429ba 100644 --- a/NotifyEx/NotifyEx.csproj +++ b/NotifyEx/NotifyEx.csproj @@ -137,6 +137,7 @@ + @@ -144,6 +145,7 @@ + diff --git a/NotifyEx/Plugin.cs b/NotifyEx/Plugin.cs index 5f065a7..f2bd0c4 100644 --- a/NotifyEx/Plugin.cs +++ b/NotifyEx/Plugin.cs @@ -20,7 +20,7 @@ namespace NotifyEx [ExportMetadata("Guid", "3190E362-3833-4953-87C3-B2C22C058EE8")] [ExportMetadata("Title", "NotifyEx")] [ExportMetadata("Description", "通知内容扩展")] - [ExportMetadata("Version", "0.5.1")] + [ExportMetadata("Version", "0.6.0")] [ExportMetadata("Author", "@Yoctillion")] public class Plugin : IPlugin, ISettings, IRequestNotify { diff --git a/NotifyEx/Properties/AssemblyInfo.cs b/NotifyEx/Properties/AssemblyInfo.cs index 50d76da..0d5aae3 100644 --- a/NotifyEx/Properties/AssemblyInfo.cs +++ b/NotifyEx/Properties/AssemblyInfo.cs @@ -51,4 +51,4 @@ // すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を // 既定値にすることができます: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.5.1")] +[assembly: AssemblyVersion("0.6.0")] diff --git a/NotifyEx/ViewModels/ToolViewModel.cs b/NotifyEx/ViewModels/ToolViewModel.cs index 27beb11..a321058 100644 --- a/NotifyEx/ViewModels/ToolViewModel.cs +++ b/NotifyEx/ViewModels/ToolViewModel.cs @@ -10,10 +10,10 @@ namespace NotifyEx.ViewModels { public class ToolViewModel : ViewModel { - private readonly ShipNotifier _shipNotifier; - private readonly SlotNotifier _slotNotifier; - private readonly HpNotifier _hpNotifier; - private readonly SupplyNotifier _supplyNotifier; + private readonly ShipNotifier _shipNotifier = ShipNotifier.Current; + private readonly SlotNotifier _slotNotifier = SlotNotifier.Current; + private readonly HpNotifier _hpNotifier = HpNotifier.Current; + private readonly SupplyNotifier _supplyNotifier = SupplyNotifier.Current; public bool EnabledShipNotifier { @@ -145,13 +145,5 @@ public bool EnabledExpenditionSupplyNotifier } } - - public ToolViewModel() - { - _shipNotifier = new ShipNotifier(); - _slotNotifier = new SlotNotifier(); - _hpNotifier = new HpNotifier(); - _supplyNotifier = new SupplyNotifier(); - } } }