├── tools.jpg ├── settings-tp.jpg ├── .nuget ├── NuGet.exe ├── NuGet.Config └── NuGet.targets ├── settings-bosshp.jpg ├── .editorconfig ├── EventMapHpViewer ├── Models │ ├── Raw │ │ ├── kcsapi_mst_maparea.cs │ │ ├── Api_Eventmap.cs │ │ ├── kcsapi_start2.cs │ │ ├── map_exboss.cs │ │ ├── map_select_eventmap_rank.cs │ │ ├── kcsapi_mst_mapinfo.cs │ │ ├── member_mapinfo.cs │ │ └── map_start_next.cs │ ├── Eventmap.cs │ ├── Rank.cs │ ├── GaugeType.cs │ ├── Maps.cs │ ├── TransportCapacity.cs │ ├── MapArea.cs │ ├── Settings │ │ ├── TpSetting.cs │ │ ├── MapHpSettings.cs │ │ ├── BossSettingsWrapper.cs │ │ ├── RemoteSettingsClient.cs │ │ └── AutoCalcTpSettings.cs │ ├── MapInfo.cs │ ├── RemainingCount.cs │ ├── TpExtensions.cs │ ├── MapData.cs │ └── MapInfoProxy.cs ├── app.config ├── Views │ ├── ToolView.xaml.cs │ ├── Settings │ │ ├── TpSettings.xaml.cs │ │ ├── BossSettings.xaml.cs │ │ ├── TpSettingsListView.xaml.cs │ │ ├── TpSettingsListView.xaml │ │ ├── TpSettings.xaml │ │ └── BossSettings.xaml │ ├── Controls │ │ ├── BossSettingsUrlRule.cs │ │ └── DecimalRule.cs │ ├── SettingsView.xaml.cs │ └── SettingsView.xaml ├── Annotations │ ├── LightAttribute.cs │ ├── DarkAttribute.cs │ └── ElementalAttribute.cs ├── Properties │ └── AssemblyInfo.cs ├── ViewModels │ ├── Settings │ │ ├── SettingsViewModel.cs │ │ ├── TpSettingsViewModel.cs │ │ └── BossSettingsViewModel.cs │ ├── ToolViewModel.cs │ └── MapViewModel.cs ├── MapHpViewer.cs ├── packages.config ├── Styles │ └── PluginStyle.xaml ├── SampleData │ └── ToolViewModelSampleData.xaml └── EventMapHpViewer.csproj ├── licenses ├── Nekoxy.txt ├── KanColleViewer.txt ├── MetroRadiance.txt ├── StatefulModel.txt ├── LGPL.txt └── Apache.txt ├── LICENSE ├── EventMapHpViewer.sln ├── README.md └── .gitignore /tools.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veigr/EventMapHpViewer/HEAD/tools.jpg -------------------------------------------------------------------------------- /settings-tp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veigr/EventMapHpViewer/HEAD/settings-tp.jpg -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veigr/EventMapHpViewer/HEAD/.nuget/NuGet.exe -------------------------------------------------------------------------------- /settings-bosshp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veigr/EventMapHpViewer/HEAD/settings-bosshp.jpg -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{cs,xaml}] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = crlf 7 | insert_final_newline = true 8 | charset = utf-8-bom 9 | -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/kcsapi_mst_maparea.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Raw 2 | { 3 | public class kcsapi_mst_maparea 4 | { 5 | public int api_id { get; set; } 6 | public string api_name { get; set; } 7 | public int api_type { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Eventmap.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models 2 | { 3 | public class Eventmap 4 | { 5 | public int? NowMapHp { get; set; } 6 | public int? MaxMapHp { get; set; } 7 | public int State { get; set; } 8 | public Rank SelectedRank { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Rank.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace EventMapHpViewer.Models 8 | { 9 | public enum Rank 10 | { 11 | 丁 = 1, 12 | 丙 = 2, 13 | 乙 = 3, 14 | 甲 = 4, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/Api_Eventmap.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Raw 2 | { 3 | public class Api_Eventmap 4 | { 5 | public int api_now_maphp { get; set; } 6 | public int api_max_maphp { get; set; } 7 | public int api_state { get; set; } 8 | public int api_selected_rank { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/kcsapi_start2.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Raw 2 | { 3 | // ReSharper disable InconsistentNaming 4 | public class kcsapi_start2 5 | { 6 | public kcsapi_mst_maparea[] api_mst_maparea { get; set; } 7 | public kcsapi_mst_mapinfo[] api_mst_mapinfo { get; set; } 8 | } 9 | // ReSharper restore InconsistentNaming 10 | } 11 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/GaugeType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace EventMapHpViewer.Models 8 | { 9 | public enum GaugeType 10 | { 11 | Normal = 0, 12 | Extra = 1, 13 | Event = 2, 14 | Transport = 3, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Maps.cs: -------------------------------------------------------------------------------- 1 | using Grabacr07.KanColleWrapper; 2 | using System.Reflection; 3 | 4 | namespace EventMapHpViewer.Models 5 | { 6 | public class Maps 7 | { 8 | public MapData[] MapList { get; set; } 9 | public static MasterTable MapAreas { get; set; } 10 | public static MasterTable MapInfos { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/map_exboss.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace EventMapHpViewer.Models.Raw 8 | { 9 | class map_exboss 10 | { 11 | public int mapid { get; set; } 12 | public int rank { get; set; } 13 | public int gauge { get; set; } 14 | public int maxhp { get; set; } 15 | public bool last { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/map_select_eventmap_rank.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Raw 2 | { 3 | public class map_select_eventmap_rank 4 | { 5 | public Api_Maphp api_maphp { get; set; } 6 | } 7 | 8 | public class Api_Maphp 9 | { 10 | public int api_now_maphp { get; set; } 11 | public int api_max_maphp { get; set; } 12 | public string api_gauge_type { get; set; } 13 | public int api_gauge_num { get; set; } 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /EventMapHpViewer/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/kcsapi_mst_mapinfo.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Raw 2 | { 3 | public class kcsapi_mst_mapinfo 4 | { 5 | public int api_id { get; set; } 6 | public int api_maparea_id { get; set; } 7 | public int api_no { get; set; } 8 | public string api_name { get; set; } 9 | public int api_level { get; set; } 10 | public string api_opetext { get; set; } 11 | public string api_infotext { get; set; } 12 | public int[] api_item { get; set; } 13 | public int? api_max_maphp { get; set; } 14 | public int? api_required_defeat_count { get; set; } 15 | public int[] api_sally_flag { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/member_mapinfo.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Raw 2 | { 3 | public class mapinfo 4 | { 5 | public member_mapinfo[] api_map_info { get; set; } 6 | } 7 | 8 | public class member_mapinfo 9 | { 10 | public int api_id { get; set; } 11 | public int api_cleared { get; set; } 12 | public int? api_defeat_count { get; set; } 13 | public int? api_required_defeat_count { get; set; } 14 | public int? api_gauge_type { get; set; } 15 | public int? api_gauge_num { get; set; } 16 | public Api_Eventmap api_eventmap { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/TransportCapacity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace EventMapHpViewer.Models 8 | { 9 | public struct TransportCapacity 10 | { 11 | private decimal _s; 12 | 13 | public decimal S 14 | { 15 | get { return _s; } 16 | set 17 | { 18 | _s = value; 19 | this.A = Math.Floor(value * 0.7m); 20 | } 21 | } 22 | 23 | public decimal A { get; private set; } 24 | 25 | public TransportCapacity(decimal s) 26 | { 27 | A = 0; 28 | _s = 0; 29 | S = s; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/ToolView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace EventMapHpViewer.Views 17 | { 18 | /// 19 | /// ToolView.xaml の相互作用ロジック 20 | /// 21 | public partial class ToolView : UserControl 22 | { 23 | public ToolView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Settings/TpSettings.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace EventMapHpViewer.Views.Settings 17 | { 18 | /// 19 | /// TpSettings.xaml の相互作用ロジック 20 | /// 21 | public partial class TpSettings : UserControl 22 | { 23 | public TpSettings() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Settings/BossSettings.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace EventMapHpViewer.Views.Settings 17 | { 18 | /// 19 | /// BossSettings.xaml の相互作用ロジック 20 | /// 21 | public partial class BossSettings : UserControl 22 | { 23 | public BossSettings() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/MapArea.cs: -------------------------------------------------------------------------------- 1 | using Grabacr07.KanColleWrapper.Models; 2 | using EventMapHpViewer.Models.Raw; 3 | 4 | namespace EventMapHpViewer.Models 5 | { 6 | public class MapArea : RawDataWrapper, IIdentifiable 7 | { 8 | public int Id { get; private set; } 9 | 10 | public string Name { get; private set; } 11 | 12 | public MapArea(kcsapi_mst_maparea maparea) 13 | : base(maparea) 14 | { 15 | this.Id = maparea.api_id; 16 | this.Name = maparea.api_name; 17 | } 18 | 19 | #region static members 20 | 21 | public static MapArea Dummy { get; } = new MapArea(new kcsapi_mst_maparea 22 | { 23 | api_id = 0, 24 | api_name = "???", 25 | }); 26 | 27 | #endregion 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /EventMapHpViewer/Annotations/LightAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Elemental Annotations 3 | * Copyright © 2015 Takeshi KIRIYA (aka takeshik) 4 | * Licensed under the zlib License; for details, see the website. 5 | */ 6 | 7 | using System; 8 | using System.Diagnostics; 9 | 10 | // ReSharper disable CheckNamespace 11 | #if ELEMENTAL_ANNOTATIONS_DEFAULT_NAMESPACE 12 | namespace Elemental.Annotations 13 | #else 14 | namespace EventMapHpViewer.Annotations 15 | #endif 16 | // ReSharper restore CheckNamespace 17 | { 18 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] 19 | [Conditional("DEBUG")] 20 | public class LightAttribute 21 | : ElementalAttribute 22 | { 23 | public const string Name = "Light"; 24 | 25 | public LightAttribute(string description = null) 26 | : base(description) 27 | { 28 | } 29 | } 30 | 31 | partial class CodeElement 32 | { 33 | public const string Light = LightAttribute.Name; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /EventMapHpViewer/Annotations/DarkAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Elemental Annotations 3 | * Copyright © 2015 Takeshi KIRIYA (aka takeshik) 4 | * Licensed under the zlib License; for details, see the website. 5 | */ 6 | 7 | using System; 8 | using System.Diagnostics; 9 | 10 | // ReSharper disable CheckNamespace 11 | #if ELEMENTAL_ANNOTATIONS_DEFAULT_NAMESPACE 12 | namespace Elemental.Annotations 13 | #else 14 | namespace EventMapHpViewer.Annotations 15 | #endif 16 | // ReSharper restore CheckNamespace 17 | { 18 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] 19 | [Conditional("DEBUG")] 20 | public class DarkAttribute 21 | : ElementalAttribute 22 | { 23 | public const string Name = "Dark"; 24 | 25 | public DarkAttribute(string description = null) 26 | : base(description) 27 | { 28 | } 29 | } 30 | 31 | partial class CodeElement 32 | { 33 | public const string Dark = DarkAttribute.Name; 34 | } 35 | } 36 | // vim:set ft=cs fenc=utf-8 ts=4 sw=4 sts=4 et: 37 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Settings/TpSetting.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Settings 2 | { 3 | public class TpSetting: Livet.NotificationObject 4 | { 5 | public int TypeId { get; set; } 6 | public string TypeName { get; set; } 7 | 8 | public int Id { get; set; } 9 | public int SortId { get; set; } 10 | public string Name { get; set; } 11 | 12 | private decimal _Tp; 13 | public decimal Tp 14 | { 15 | get => this._Tp; 16 | set 17 | { 18 | if (this._Tp == value) 19 | return; 20 | this._Tp = value; 21 | this.RaisePropertyChanged(); 22 | } 23 | } 24 | 25 | public TpSetting() { } 26 | 27 | public TpSetting(int id, int sortId, string name, decimal tp = 0, int typeId = 0, string typeName = "") 28 | { 29 | this.Id = id; 30 | this.SortId = sortId; 31 | this.Name = name; 32 | this.Tp = tp; 33 | this.TypeId = typeId; 34 | this.TypeName = typeName; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /licenses/Nekoxy.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 veigr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 veigr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /licenses/KanColleViewer.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Grabacr07 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /licenses/MetroRadiance.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Manato KAMEYA 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /licenses/StatefulModel.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Masanori Onoue 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Controls/BossSettingsUrlRule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | using EventMapHpViewer.Models.Settings; 8 | 9 | namespace EventMapHpViewer.Views.Controls 10 | { 11 | public class BossSettingsUrlRule : ValidationRule 12 | { 13 | public bool AllowsEmpty { get; set; } 14 | 15 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 16 | { 17 | var urlAsString = value as string; 18 | if (string.IsNullOrEmpty(urlAsString)) 19 | { 20 | return this.AllowsEmpty 21 | ? new ValidationResult(true, null) 22 | : new ValidationResult(false, "値を入力してください。"); 23 | } 24 | 25 | var url = RemoteSettingsClient.BuildBossSettingsUrl(urlAsString, 0, 0, 0); 26 | 27 | if(Uri.TryCreate(url, UriKind.Absolute, out var _)) 28 | { 29 | return new ValidationResult(true, null); 30 | } 31 | else 32 | { 33 | return new ValidationResult(false, "URL 形式を入力して下さい。"); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/SettingsView.xaml.cs: -------------------------------------------------------------------------------- 1 | using MetroRadiance.UI.Controls; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace EventMapHpViewer.Views 18 | { 19 | /// 20 | /// SettingsView.xaml の相互作用ロジック 21 | /// 22 | public partial class SettingsView : UserControl 23 | { 24 | public SettingsView() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | private void UserControl_Loaded(object sender, RoutedEventArgs e) 30 | { 31 | var window = FindAncestor(this); 32 | window.Width = 800; 33 | window.Height = 600; 34 | } 35 | 36 | private static T FindAncestor(DependencyObject current) where T : DependencyObject 37 | { 38 | var parent = VisualTreeHelper.GetParent(current); 39 | if (parent is T) 40 | return (T)parent; 41 | else 42 | return FindAncestor(parent); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Raw/map_start_next.cs: -------------------------------------------------------------------------------- 1 | namespace EventMapHpViewer.Models.Raw 2 | { 3 | public class map_start_next 4 | { 5 | public int api_rashin_flg { get; set; } 6 | public int api_rashin_id { get; set; } 7 | public int api_maparea_id { get; set; } 8 | public int api_mapinfo_no { get; set; } 9 | public int api_no { get; set; } 10 | public int api_color_no { get; set; } 11 | public int api_event_id { get; set; } 12 | public int api_event_kind { get; set; } 13 | public int api_next { get; set; } 14 | public int api_bosscell_no { get; set; } 15 | public int api_bosscomp { get; set; } 16 | public Api_Eventmap api_eventmap { get; set; } 17 | public int api_comment_kind { get; set; } 18 | public int api_production_kind { get; set; } 19 | public Api_Enemy api_enemy { get; set; } 20 | public Api_Happening api_happening { get; set; } 21 | } 22 | 23 | public class Api_Enemy 24 | { 25 | public int api_enemy_id { get; set; } 26 | public int api_result { get; set; } 27 | public string api_result_str { get; set; } 28 | } 29 | 30 | public class Api_Happening 31 | { 32 | public int api_type { get; set; } 33 | public int api_count { get; set; } 34 | public int api_usemst { get; set; } 35 | public int api_mst_id { get; set; } 36 | public int api_icon_id { get; set; } 37 | public int api_dentan { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /EventMapHpViewer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using System.Windows; 5 | 6 | // アセンブリに関する一般情報は以下の属性セットをとおして制御されます。 7 | // アセンブリに関連付けられている情報を変更するには、 8 | // これらの属性値を変更してください。 9 | [assembly: AssemblyTitle("EventMapHpViewer")] 10 | [assembly: AssemblyDescription("KanColleViewer で イベントマップのHPを表示するプラグイン")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("EventMapHpViewer")] 14 | [assembly: AssemblyCopyright("Copyright © 2014 veigr")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // ComVisible を false に設定すると、その型はこのアセンブリ内で COM コンポーネントから 19 | // 参照不可能になります。COM からこのアセンブリ内の型にアクセスする場合は、 20 | // その型の ComVisible 属性を true に設定してください。 21 | [assembly: ComVisible(false)] 22 | 23 | [assembly: ThemeInfo( 24 | ResourceDictionaryLocation.None, //テーマ固有のリソース ディクショナリが置かれている場所 25 | //(リソースがページ、 26 | //またはアプリケーション リソース ディクショナリに見つからない場合に使用されます) 27 | ResourceDictionaryLocation.SourceAssembly //汎用リソース ディクショナリが置かれている場所 28 | //(リソースがページ、 29 | //アプリケーション、またはいずれのテーマ固有のリソース ディクショナリにも見つからない場合に使用されます) 30 | )] 31 | 32 | 33 | // 次の GUID は、このプロジェクトが COM に公開される場合の、typelib の ID です 34 | [assembly: Guid("101436f4-9308-4892-a88a-19efbdf2ed5f")] 35 | 36 | // アセンブリのバージョン情報は、以下の 4 つの値で構成されています: 37 | // 38 | // Major Version 39 | // Minor Version 40 | // Build Number 41 | // Revision 42 | // 43 | // すべての値を指定するか、下のように '*' を使ってビルドおよびリビジョン番号を 44 | // 既定値にすることができます: 45 | // [assembly: AssemblyVersion("1.0.*")] 46 | [assembly: AssemblyVersion("3.4.2.0")] 47 | -------------------------------------------------------------------------------- /EventMapHpViewer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.22823.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventMapHpViewer", "EventMapHpViewer\EventMapHpViewer.csproj", "{912029C5-C147-459B-A735-3D559B2F193D}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{781AAEBD-E3D5-43E4-9E2A-6398570D8C3F}" 9 | ProjectSection(SolutionItems) = preProject 10 | .nuget\NuGet.Config = .nuget\NuGet.Config 11 | .nuget\NuGet.exe = .nuget\NuGet.exe 12 | .nuget\NuGet.targets = .nuget\NuGet.targets 13 | EndProjectSection 14 | EndProject 15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{22D0D515-2A6A-41AF-9BA2-DFE01C4A090B}" 16 | ProjectSection(SolutionItems) = preProject 17 | README.md = README.md 18 | EndProjectSection 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {912029C5-C147-459B-A735-3D559B2F193D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {912029C5-C147-459B-A735-3D559B2F193D}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {912029C5-C147-459B-A735-3D559B2F193D}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {912029C5-C147-459B-A735-3D559B2F193D}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /EventMapHpViewer/ViewModels/Settings/SettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using Grabacr07.KanColleWrapper; 2 | using Livet; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using MetroTrilithon.Mvvm; 10 | using StatefulModel; 11 | using EventMapHpViewer.Models.Settings; 12 | 13 | namespace EventMapHpViewer.ViewModels.Settings 14 | { 15 | public class SettingsViewModel : ViewModel 16 | { 17 | public BossSettingsViewModel BossSettings { get; } 18 | public TpSettingsViewModel TpSettings { get; } 19 | 20 | public SettingsViewModel() 21 | { 22 | this.BossSettings = new BossSettingsViewModel(); 23 | this.TpSettings = new TpSettingsViewModel 24 | { 25 | TransportCapacityS = MapHpSettings.TransportCapacityS.Value 26 | }; 27 | 28 | KanColleClient.Current.Subscribe(nameof(KanColleClient.Current.IsStarted), () => 29 | DispatcherHelper.UIDispatcher.Invoke(this.Initialize) 30 | , false) 31 | .AddTo(this); 32 | } 33 | 34 | private void Initialize() 35 | { 36 | this.BossSettings.MapItemsSource 37 | = Models.Maps.MapInfos 38 | .Where(x => 20 < x.Value.MapAreaId) 39 | .Select(x => x.Value) 40 | .Select(x => new KeyValuePair(x.Id, $"{x.MapAreaId}-{x.IdInEachMapArea} : {x.Name} - {x.OperationName}")) 41 | .ToArray(); 42 | this.BossSettings.IsEnabled = true; 43 | 44 | this.TpSettings.Settings.UpdateFromMaster(); 45 | this.TpSettings.IsEnabled = true; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /EventMapHpViewer/MapHpViewer.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.Composition; 2 | using EventMapHpViewer.Models; 3 | using EventMapHpViewer.ViewModels; 4 | using EventMapHpViewer.ViewModels.Settings; 5 | using EventMapHpViewer.Views; 6 | using Grabacr07.KanColleViewer.Composition; 7 | 8 | namespace EventMapHpViewer 9 | { 10 | [Export(typeof(IPlugin))] 11 | [Export(typeof(ITool))] 12 | [Export(typeof(ISettings))] 13 | [ExportMetadata("Guid", "101436F4-9308-4892-A88A-19EFBDF2ED5F")] 14 | [ExportMetadata("Title", title)] 15 | [ExportMetadata("Description", "Map HPを表示します。")] 16 | [ExportMetadata("Version", version)] 17 | [ExportMetadata("Author", "@veigr")] 18 | public class MapHpViewer : IPlugin, ITool, ISettings 19 | { 20 | internal const string title = "MapHPViewer"; 21 | internal const string version = "3.4.2"; 22 | private ToolViewModel toolVm; 23 | private SettingsViewModel settingsVm; 24 | 25 | public void Initialize() 26 | { 27 | this.toolVm = new ToolViewModel(new MapInfoProxy()); 28 | this.settingsVm = new SettingsViewModel(); 29 | } 30 | 31 | public string Name => "MapHP"; 32 | 33 | // タブ表示するたびに new されてしまうが、今のところ new しないとマルチウィンドウで正常に表示されない 34 | object ITool.View => new ToolView { DataContext = this.toolVm }; 35 | 36 | private SettingsView settingsViewCache; 37 | object ISettings.View 38 | { 39 | get 40 | { 41 | // なぜかViewを使い回さずVMだけ使い回し、Viewを作り直すとUseAutoCalcTpSettingsのRadioButtonでStackOverFlowが発生する。 42 | if (settingsViewCache == null) 43 | this.settingsViewCache = new SettingsView { DataContext = this.settingsVm }; 44 | return this.settingsViewCache; 45 | } 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /EventMapHpViewer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/MapInfo.cs: -------------------------------------------------------------------------------- 1 | using Grabacr07.KanColleWrapper; 2 | using Grabacr07.KanColleWrapper.Models; 3 | using EventMapHpViewer.Models.Raw; 4 | 5 | namespace EventMapHpViewer.Models 6 | { 7 | public class MapInfo : RawDataWrapper, IIdentifiable 8 | { 9 | public int Id { get; } 10 | 11 | public string Name { get; private set; } 12 | 13 | public int MapAreaId { get; private set; } 14 | 15 | public MapArea MapArea { get; private set; } 16 | 17 | public int IdInEachMapArea { get; private set; } 18 | 19 | public int Level { get; private set; } 20 | 21 | public string OperationName { get; private set; } 22 | 23 | public string OperationSummary { get; private set; } 24 | 25 | public int RequiredDefeatCount { get; private set; } 26 | 27 | public MapInfo(kcsapi_mst_mapinfo mapinfo, MasterTable mapAreas) 28 | : base(mapinfo) 29 | { 30 | this.Id = mapinfo.api_id; 31 | this.Name = mapinfo.api_name; 32 | this.MapAreaId = mapinfo.api_maparea_id; 33 | this.MapArea = mapAreas[mapinfo.api_maparea_id] ?? MapArea.Dummy; 34 | this.IdInEachMapArea = mapinfo.api_no; 35 | this.Level = mapinfo.api_level; 36 | this.OperationName = mapinfo.api_opetext; 37 | this.OperationSummary = mapinfo.api_infotext; 38 | this.RequiredDefeatCount = mapinfo.api_required_defeat_count ?? 1; 39 | } 40 | 41 | #region static members 42 | 43 | public static MapInfo Dummy { get; } = new MapInfo(new kcsapi_mst_mapinfo 44 | { 45 | api_id = 0, 46 | api_name = "???", 47 | api_maparea_id = 0, 48 | api_no = 0, 49 | api_level = 0, 50 | }, new MasterTable()); 51 | 52 | #endregion 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/SettingsView.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Controls/DecimalRule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | 8 | namespace EventMapHpViewer.Views.Controls 9 | { 10 | /// 11 | /// 入力された値が有効な 値かどうかを検証します。 12 | /// 13 | public class DecimalRule : ValidationRule 14 | { 15 | /// 16 | /// 入力に空文字を許可するかどうかを示す値を取得または設定します。 17 | /// 18 | public bool AllowsEmpty { get; set; } 19 | 20 | /// 21 | /// 入力可能な最小値を取得または設定します。 22 | /// 23 | /// 24 | /// 入力可能な最小値。最小値がない場合は null。 25 | /// 26 | public decimal? Min { get; set; } 27 | 28 | /// 29 | /// 入力可能な最大値を取得または設定します。 30 | /// 31 | /// 32 | /// 入力可能な最大値。最大値がない場合は null。 33 | /// 34 | public decimal? Max { get; set; } 35 | 36 | public override ValidationResult Validate(object value, CultureInfo cultureInfo) 37 | { 38 | var numberAsString = value as string; 39 | if (string.IsNullOrEmpty(numberAsString)) 40 | { 41 | return this.AllowsEmpty 42 | ? new ValidationResult(true, null) 43 | : new ValidationResult(false, "値を入力してください。"); 44 | } 45 | 46 | if(!decimal.TryParse(numberAsString, out var number)) 47 | return new ValidationResult(false, "数値を入力してください。"); 48 | 49 | if (this.Min.HasValue && number < this.Min) 50 | { 51 | return new ValidationResult(false, $"{this.Min} 以上の数値を入力してください。"); 52 | } 53 | 54 | if (this.Max.HasValue && this.Max < number) 55 | { 56 | return new ValidationResult(false, $"{this.Max} 以下の数値を入力してください。"); 57 | } 58 | 59 | return new ValidationResult(true, null); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/RemainingCount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace EventMapHpViewer.Models 8 | { 9 | public class RemainingCount 10 | { 11 | public int Min { get; set; } 12 | public int Max { get; set; } 13 | 14 | public RemainingCount() 15 | { 16 | this.Min = 0; 17 | this.Max = 0; 18 | } 19 | public RemainingCount(int min, int max) 20 | { 21 | this.Min = min; 22 | this.Max = max; 23 | } 24 | public RemainingCount(int value) 25 | { 26 | this.Min = value; 27 | this.Max = value; 28 | } 29 | 30 | public bool IsSingleValue => this.Min == this.Max; 31 | 32 | public override bool Equals(object obj) 33 | { 34 | return obj is RemainingCount && this.Equals((RemainingCount)obj); 35 | } 36 | 37 | public override int GetHashCode() 38 | { 39 | unchecked 40 | { 41 | return (this.Min.GetHashCode() * 397) ^ this.Max.GetHashCode(); 42 | } 43 | } 44 | 45 | public override string ToString() 46 | { 47 | return $"{this.Min}-{this.Max}"; 48 | } 49 | 50 | public static bool operator ==(RemainingCount value1, RemainingCount value2) 51 | { 52 | if (ReferenceEquals(value1, value2)) return true; 53 | return value1?.Equals(value2) ?? false; 54 | } 55 | 56 | public static bool operator !=(RemainingCount id1, RemainingCount id2) 57 | { 58 | return !(id1 == id2); 59 | } 60 | 61 | private bool Equals(RemainingCount other) 62 | { 63 | if (ReferenceEquals(null, other)) return false; 64 | if (ReferenceEquals(this, other)) return true; 65 | return this.Min == other.Min 66 | && this.Max == other.Max; 67 | } 68 | 69 | public static readonly RemainingCount MaxValue = new RemainingCount(int.MaxValue); 70 | public static readonly RemainingCount Zero = new RemainingCount(0); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/TpExtensions.cs: -------------------------------------------------------------------------------- 1 | using Grabacr07.KanColleWrapper; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using EventMapHpViewer.Models.Settings; 8 | using Grabacr07.KanColleWrapper.Models; 9 | 10 | namespace EventMapHpViewer.Models 11 | { 12 | static class TpExtensions 13 | { 14 | public static TransportCapacity TransportationCapacity(this Organization org) 15 | { 16 | if (!MapHpSettings.UseAutoCalcTpSettings.Value) 17 | return new TransportCapacity(MapHpSettings.TransportCapacityS.Value); 18 | 19 | var settings = AutoCalcTpSettings.FromSettings; 20 | var tp = org.TransportingShips() 21 | .PossibleTransport() 22 | .Sum(x => x.CalcTp(settings)); 23 | return new TransportCapacity(tp); 24 | } 25 | 26 | public static decimal CalcTp(this Ship ship, AutoCalcTpSettings settings) 27 | { 28 | var stypeTp = settings.ShipTypeTp 29 | .FirstOrDefault(x => x.Id == ship.Info.ShipType.Id)?.Tp 30 | ?? 0; 31 | 32 | var shipTp = settings.ShipTp 33 | .FirstOrDefault(x => x.Id == ship.Info.Id)?.Tp 34 | ?? 0; 35 | 36 | var slotTp = ship.Slots 37 | .Concat(new[] { ship.ExSlot }) 38 | .Where(x => x.Equipped) 39 | .Select(x => x.Item.Info.Id) 40 | .Sum(x => settings.SlotItemTp.FirstOrDefault(y => y.Id == x)?.Tp ?? 0); 41 | 42 | return stypeTp + shipTp + slotTp; 43 | } 44 | 45 | private static IEnumerable TransportingShips(this Organization org) 46 | { 47 | var ships = org.Combined 48 | ? org.CombinedFleet.Fleets.SelectMany(x => x.Ships) 49 | : org.Fleets[1].Ships; 50 | return ships.PossibleTransport(); 51 | } 52 | 53 | private static IEnumerable PossibleTransport(this IEnumerable ships) 54 | { 55 | return ships 56 | .Where(ship => !ship.Situation.HasFlag(ShipSituation.Evacuation)) 57 | .Where(ship => !ship.Situation.HasFlag(ShipSituation.Tow)) 58 | .Where(ship => !ship.Situation.HasFlag(ShipSituation.HeavilyDamaged)); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MapHP Plugin 2 | ================ 3 | 4 | KanColleViewer で、攻略中マップのHPと最低必要撃破回数を一覧表示するプラグインです。 5 | 6 | * イベント海域では、マップHPとゲージ破壊に最低限必要なボス撃破回数を表示します 7 | * 通常海域では、必要なボス撃破回数と現時点での残り撃破回数を表示します 8 | * 「艦これ戦術データリンク」からデータ取得を行っています 9 | 10 | ![ツール画面](tools.jpg) 11 | 12 | ![ボスHP設定](settings-bosshp.jpg) 13 | 14 | ![TP設定](settings-tp.jpg) 15 | 16 | ### インストール 17 | 18 | * `EventMapHpViewer.dll` を KanColleViewer の `Plugins` ディレクトリに放り込んで下さい。 19 | 20 | 21 | ### ライセンス 22 | 23 | * [The MIT License (MIT)](LICENSE) 24 | 25 | 26 | ### 使用ライブラリ 27 | 28 | #### [KanColleViewer](https://github.com/Grabacr07/KanColleViewer) 29 | 30 | > The MIT License (MIT) 31 | > 32 | > Copyright (c) 2013 Grabacr07 33 | 34 | * **ライセンス :** The MIT License (MIT) 35 | * **ライセンス全文 :** [licenses/KanColleViewer.txt](licenses/KanColleViewer.txt) 36 | 37 | #### [MetroRadiance](https://github.com/Grabacr07/MetroRadiance) 38 | 39 | > The MIT License (MIT) 40 | > 41 | > Copyright (c) 2014 Manato KAMEYA 42 | 43 | * **ライセンス :** The MIT License (MIT) 44 | * **ライセンス全文 :** [licenses/MetroRadiance.txt](licenses/MetroRadiance.txt) 45 | 46 | #### [Livet](http://ugaya40.hateblo.jp/entry/Livet) 47 | 48 | * **ライセンス :** zlib/libpng 49 | 50 | #### [StatefulModel](http://ugaya40.hateblo.jp/entry/StatefulModel) 51 | 52 | > The MIT License (MIT) 53 | > 54 | > Copyright (c) 2015 Masanori Onoue 55 | 56 | * **用途 :** M-V-Whatever の Model 向けインフラストラクチャ 57 | * **ライセンス :** The MIT License (MIT) 58 | * **ライセンス全文 :** [licenses/StatefulModel.txt](licenses/StatefulModel.txt) 59 | 60 | #### [Nekoxy](https://github.com/veigr/Nekoxy) 61 | 62 | > The MIT License (MIT) 63 | > 64 | > Copyright (c) 2015 veigr 65 | 66 | * **ライセンス :** The MIT License (MIT) 67 | * **ライセンス全文 :** [licenses/Nekoxy.txt](licenses/Nekoxy.txt) 68 | 69 | #### [TrotiNet](https://github.com/krys-g/TrotiNet) 70 | 71 | > TrotiNet is a proxy library implemented in C#. It aims at delivering a simple, 72 | > reusable framework for developing any sort of C# proxies. 73 | > 74 | > TrotiNet is distributed under the GNU Lesser General Public License v3.0 75 | > (LGPL). See: http://www.gnu.org/licenses/lgpl.html 76 | 77 | * **ライセンス :** GNU LESSER GENERAL PUBLIC LICENSE Version 3 78 | * **ライセンス全文 :** [licenses/LGPL.txt](licenses/LGPL.txt) , [licenses/GPL.txt](licenses/GPL.txt) 79 | 80 | #### [Apache log4net](https://logging.apache.org/log4net/) 81 | 82 | * **ライセンス :** Apache License Version 2.0 83 | * **ライセンス全文 :** [licenses/Apache.txt](licenses/Apache.txt) 84 | 85 | #### [Rx (Reactive Extensions)](https://rx.codeplex.com/) 86 | 87 | * **ライセンス :** Apache License Version 2.0 88 | * **ライセンス全文 :** [licenses/Apache.txt](licenses/Apache.txt) 89 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Settings/TpSettingsListView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace EventMapHpViewer.Views.Settings 17 | { 18 | /// 19 | /// TpSettingsListView.xaml の相互作用ロジック 20 | /// 21 | public partial class TpSettingsListView : UserControl 22 | { 23 | public TpSettingsListView() 24 | { 25 | InitializeComponent(); 26 | } 27 | 28 | public double IdColumnWidth 29 | { 30 | get { return (double)GetValue(IdColumnWidthProperty); } 31 | set { SetValue(IdColumnWidthProperty, value); } 32 | } 33 | public static readonly DependencyProperty IdColumnWidthProperty = 34 | DependencyProperty.Register(nameof(IdColumnWidth), typeof(double), typeof(TpSettingsListView), new PropertyMetadata(double.NaN)); 35 | 36 | public double NameColumnWidth 37 | { 38 | get { return (double)GetValue(NameColumnWidthProperty); } 39 | set { SetValue(NameColumnWidthProperty, value); } 40 | } 41 | public static readonly DependencyProperty NameColumnWidthProperty = 42 | DependencyProperty.Register(nameof(NameColumnWidth), typeof(double), typeof(TpSettingsListView), new PropertyMetadata(double.NaN)); 43 | 44 | public double TpColumnWidth 45 | { 46 | get { return (double)GetValue(TpColumnWidthProperty); } 47 | set { SetValue(TpColumnWidthProperty, value); } 48 | } 49 | public static readonly DependencyProperty TpColumnWidthProperty = 50 | DependencyProperty.Register(nameof(TpColumnWidth), typeof(double), typeof(TpSettingsListView), new PropertyMetadata(double.NaN)); 51 | 52 | public double TypeIdColumnWidth 53 | { 54 | get { return (double)GetValue(TypeIdColumnWidthProperty); } 55 | set { SetValue(TypeIdColumnWidthProperty, value); } 56 | } 57 | public static readonly DependencyProperty TypeIdColumnWidthProperty = 58 | DependencyProperty.Register(nameof(TypeIdColumnWidth), typeof(double), typeof(TpSettingsListView), new PropertyMetadata(double.NaN)); 59 | 60 | public double TypeNameColumnWidth 61 | { 62 | get { return (double)GetValue(TypeNameColumnWidthProperty); } 63 | set { SetValue(TypeNameColumnWidthProperty, value); } 64 | } 65 | public static readonly DependencyProperty TypeNameColumnWidthProperty = 66 | DependencyProperty.Register(nameof(TypeNameColumnWidth), typeof(double), typeof(TpSettingsListView), new PropertyMetadata(double.NaN)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Settings/MapHpSettings.cs: -------------------------------------------------------------------------------- 1 | using Codeplex.Data; 2 | using MetroTrilithon.Serialization; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Runtime.CompilerServices; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace EventMapHpViewer.Models.Settings 12 | { 13 | static class MapHpSettings 14 | { 15 | public static readonly string RoamingFilePath = Path.Combine( 16 | Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), 17 | "cat-ears.net", "MapHPViewer", "Settings.xaml"); 18 | 19 | private static readonly ISerializationProvider roamingProvider = new FileSettingsProvider(RoamingFilePath); 20 | 21 | #region TpSettings 22 | 23 | public static SerializableProperty TransportCapacityS { get; } 24 | = new SerializableProperty(GetKey(), roamingProvider) { AutoSave = true }; 25 | 26 | public static SerializableProperty ShipTypeTpSettings { get; } 27 | = new SerializableProperty(GetKey(), roamingProvider, 28 | DynamicJson.Serialize(AutoCalcTpSettings.Default.ShipTypeTp.ToArray() 29 | )) { AutoSave = true }; 30 | 31 | public static SerializableProperty SlotItemTpSettings { get; } 32 | = new SerializableProperty(GetKey(), roamingProvider, 33 | DynamicJson.Serialize(AutoCalcTpSettings.Default.SlotItemTp.ToArray() 34 | )) { AutoSave = true }; 35 | 36 | public static SerializableProperty ShipTpSettings { get; } 37 | = new SerializableProperty(GetKey(), roamingProvider, 38 | DynamicJson.Serialize(AutoCalcTpSettings.Default.ShipTp.ToArray() 39 | )) { AutoSave = true }; 40 | 41 | public static SerializableProperty UseAutoCalcTpSettings { get; } 42 | = new SerializableProperty(GetKey(), roamingProvider, 43 | true 44 | ) { AutoSave = true }; 45 | 46 | #endregion 47 | 48 | #region BossHpSettings 49 | 50 | public static SerializableProperty BossSettings { get; } 51 | = new SerializableProperty(GetKey(), roamingProvider) { AutoSave = true }; 52 | 53 | public static SerializableProperty UseLocalBossSettings { get; } 54 | = new SerializableProperty(GetKey(), roamingProvider, 55 | false 56 | ) { AutoSave = true }; 57 | 58 | public static SerializableProperty RemoteBossSettingsUrl { get; } 59 | = new SerializableProperty(GetKey(), roamingProvider, 60 | "https://kctadilstorage.blob.core.windows.net/viewer/maphp/{mapId}/{rank}/{gaugeNum}.json" 61 | ) { AutoSave = true }; 62 | 63 | #endregion 64 | 65 | private static string GetKey([CallerMemberName] string propertyName = "") 66 | => $"{nameof(MapHpSettings)}.{propertyName}"; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Settings/BossSettingsWrapper.cs: -------------------------------------------------------------------------------- 1 | using Codeplex.Data; 2 | using StatefulModel; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using MetroTrilithon.Mvvm; 10 | 11 | namespace EventMapHpViewer.Models.Settings 12 | { 13 | class BossSettingsWrapper: Livet.NotificationObject 14 | { 15 | private ObservableSynchronizedCollection _List; 16 | public ObservableSynchronizedCollection List 17 | { 18 | get => this._List; 19 | private set 20 | { 21 | if (this._List == value) 22 | return; 23 | this._List = value; 24 | this.RaisePropertyChanged(); 25 | } 26 | } 27 | 28 | public BossSettingsWrapper(string json = "") 29 | { 30 | try 31 | { 32 | BossSettingForParse[] parsed = DynamicJson.Parse(json); 33 | this.List = new ObservableSynchronizedCollection(parsed.Select(x => x.ToValue())); 34 | } 35 | catch 36 | { 37 | this.List = new ObservableSynchronizedCollection(); 38 | } 39 | } 40 | 41 | public static IEnumerable Parse(IEnumerable source) 42 | { 43 | return source.Select(x => new BossSetting 44 | { 45 | MapId = x.mapid, 46 | Rank = x.rank, 47 | GaugeNum = x.gauge, 48 | BossHP = x.maxhp, 49 | IsLast = x.last, 50 | }); 51 | } 52 | 53 | public static BossSettingsWrapper FromSettings 54 | { 55 | get => new BossSettingsWrapper(MapHpSettings.BossSettings?.Value); 56 | } 57 | } 58 | 59 | public class BossSetting 60 | { 61 | public int MapId { get; set; } 62 | public int Rank { get; set; } 63 | public int? GaugeNum { get; set; } 64 | public int BossHP { get; set; } 65 | public bool IsLast { get; set; } 66 | } 67 | 68 | public class BossSettingForParse 69 | { 70 | public int MapId { get; set; } 71 | public int Rank { get; set; } 72 | public string GaugeNum { get; set; } // DynamicJson は int? に Parse できない 73 | public int BossHP { get; set; } 74 | public bool IsLast { get; set; } 75 | public BossSetting ToValue() 76 | => new BossSetting 77 | { 78 | MapId = this.MapId, 79 | Rank = this.Rank, 80 | GaugeNum = int.TryParse(this.GaugeNum, out var num) ? num : (int?)null, 81 | BossHP = this.BossHP, 82 | IsLast = this.IsLast, 83 | }; 84 | } 85 | 86 | static class BossSettingsWrapperExtensions 87 | { 88 | public static void Save(this BossSettingsWrapper settings) 89 | => MapHpSettings.BossSettings.Value = DynamicJson.Serialize(settings.List); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /EventMapHpViewer/Annotations/ElementalAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Elemental Annotations 3 | * Copyright © 2015 Takeshi KIRIYA (aka takeshik) 4 | * Licensed under the zlib License; for details, see the website. 5 | */ 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Diagnostics; 10 | using System.Linq; 11 | using System.Reflection; 12 | 13 | // ReSharper disable CheckNamespace 14 | #if ELEMENTAL_ANNOTATIONS_DEFAULT_NAMESPACE 15 | namespace Elemental.Annotations 16 | #else 17 | namespace EventMapHpViewer.Annotations 18 | #endif 19 | // ReSharper restore CheckNamespace 20 | { 21 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] 22 | [Conditional("DEBUG")] 23 | public abstract class ElementalAttribute 24 | : Attribute 25 | { 26 | public string Description { get; private set; } 27 | 28 | protected ElementalAttribute(string description = null) 29 | { 30 | this.Description = description; 31 | } 32 | } 33 | 34 | public static partial class CodeElement 35 | { 36 | private static readonly Lazy> _elements = 37 | new Lazy>(() => typeof(CodeElement).GetTypeInfo().Assembly.DefinedTypes 38 | .Where(x => x.IsSubclassOf(typeof(ElementalAttribute))) 39 | .ToDictionary(x => x.AsType(), x => (string) x.GetDeclaredField("Name").GetValue(null)) 40 | ); 41 | 42 | public static IEnumerable Types 43 | { 44 | get 45 | { 46 | return _elements.Value.Keys; 47 | } 48 | } 49 | 50 | public static IEnumerable Names 51 | { 52 | get 53 | { 54 | return _elements.Value.Values; 55 | } 56 | } 57 | 58 | public static ILookup GetElements(MemberInfo member, bool inherit = true) 59 | { 60 | return member.GetCustomAttributes(typeof(ElementalAttribute), inherit) 61 | .Cast() 62 | .MakeLookup(); 63 | } 64 | 65 | public static ILookup GetElements(ParameterInfo parameter, bool inherit = true) 66 | { 67 | return parameter.GetCustomAttributes(typeof(ElementalAttribute), inherit) 68 | .Cast() 69 | .MakeLookup(); 70 | } 71 | 72 | public static ILookup GetElements(Module module) 73 | { 74 | return module.GetCustomAttributes(typeof(ElementalAttribute)) 75 | .Cast() 76 | .MakeLookup(); 77 | } 78 | 79 | public static ILookup GetElements(Assembly assembly) 80 | { 81 | return assembly.GetCustomAttributes(typeof(ElementalAttribute)) 82 | .Cast() 83 | .MakeLookup(); 84 | } 85 | 86 | private static ILookup MakeLookup(this IEnumerable attributes) 87 | { 88 | return attributes.ToLookup(x => _elements.Value[x.GetType()], x => x.Description); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /EventMapHpViewer/Styles/PluginStyle.xaml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 42 | 43 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/MapData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | using Codeplex.Data; 8 | using EventMapHpViewer.Models.Settings; 9 | using Grabacr07.KanColleWrapper; 10 | using Nekoxy; 11 | 12 | namespace EventMapHpViewer.Models 13 | { 14 | public class MapData 15 | { 16 | private readonly RemoteSettingsClient client = new RemoteSettingsClient(); 17 | public int Id { get; set; } 18 | public int IsCleared { get; set; } 19 | public int DefeatCount { get; set; } 20 | public int RequiredDefeatCount { get; set; } 21 | public Eventmap Eventmap { get; set; } 22 | public GaugeType GaugeType { get; set; } 23 | public int? GaugeNum { get; set; } 24 | 25 | public MapInfo Master => Maps.MapInfos[this.Id]; 26 | 27 | public string MapNumber => this.Master.MapAreaId + "-" + this.Master.IdInEachMapArea; 28 | 29 | public string Name => this.Master.Name; 30 | 31 | public string AreaName => this.Master.MapArea.Name; 32 | 33 | public int? Max 34 | { 35 | get 36 | { 37 | if (this.RequiredDefeatCount > 0) return this.RequiredDefeatCount; 38 | return this.Eventmap != null 39 | ? this.Eventmap.MaxMapHp 40 | : 1; 41 | } 42 | } 43 | 44 | public int? Current 45 | { 46 | get 47 | { 48 | if (this.RequiredDefeatCount > 0) return this.RequiredDefeatCount - this.DefeatCount; //ゲージ有り通常海域 49 | return this.Eventmap != null 50 | ? this.Eventmap.NowMapHp // イベント海域 51 | : 1; // ゲージ無し通常海域 52 | } 53 | } 54 | 55 | /// 56 | /// 残回数。輸送の場合はA勝利の残回数。 57 | /// 58 | public async Task GetRemainingCount() 59 | { 60 | if (this.IsCleared == 1) return RemainingCount.Zero; 61 | 62 | if (!this.Current.HasValue) return null; //難易度切り替え直後 63 | 64 | if (this.RequiredDefeatCount > 0) return new RemainingCount(this.Current.Value); //ゲージ有り通常海域 65 | 66 | if (this.Eventmap == null) return new RemainingCount(1); //ゲージ無し通常海域 67 | 68 | if (this.GaugeType == GaugeType.Transport) 69 | { 70 | var capacity = KanColleClient.Current.Homeport.Organization.TransportationCapacity(); 71 | if (capacity.A == 0) return RemainingCount.MaxValue; //ゲージ減らない 72 | return new RemainingCount((int)Math.Ceiling((decimal)this.Current / capacity.A)); 73 | } 74 | 75 | if (this.Eventmap.SelectedRank == 0) return null; //難易度未選択 76 | 77 | if (MapHpSettings.UseLocalBossSettings) 78 | { 79 | var settings = BossSettingsWrapper.FromSettings.List 80 | .Where(x => x.MapId == this.Id) 81 | .Where(x => x.Rank == (int)this.Eventmap.SelectedRank) 82 | .Where(x => x.GaugeNum == this.GaugeNum) 83 | .ToArray(); 84 | if (settings.Any()) 85 | return this.CalculateRemainingCount(settings); 86 | } 87 | else 88 | { 89 | var remoteBossData = await client.GetSettings( 90 | RemoteSettingsClient.BuildBossSettingsUrl( 91 | MapHpSettings.RemoteBossSettingsUrl, 92 | this.Id, 93 | (int)this.Eventmap.SelectedRank, 94 | this.GaugeNum ?? 0)); // GaugeNum がない場合 0 とみなす(リモート設定は空にしても 0 になるので) 95 | client.CloseConnection(); 96 | 97 | if (remoteBossData == null) 98 | return null; 99 | 100 | if (!remoteBossData.Any(x => x.last)) 101 | return null; 102 | 103 | if(!remoteBossData.Any(x => !x.last)) 104 | return null; 105 | 106 | return this.CalculateRemainingCount(BossSettingsWrapper.Parse(remoteBossData)); //イベント海域(リモートデータ) 107 | } 108 | 109 | return null; //未対応 110 | } 111 | 112 | private RemainingCount CalculateRemainingCount(IEnumerable settings) 113 | { 114 | var normals = settings.Where(x => !x.IsLast); 115 | var lasts = settings.Where(x => x.IsLast); 116 | if (!normals.Any() || !lasts.Any()) 117 | return null; 118 | return new RemainingCount( 119 | CalculateRemainingCount( 120 | normals.Max(x => x.BossHP), 121 | lasts.Max(x => x.BossHP) 122 | ), 123 | CalculateRemainingCount( 124 | normals.Min(x => x.BossHP), 125 | lasts.Min(x => x.BossHP) 126 | )); 127 | } 128 | 129 | private int CalculateRemainingCount(int normalBossHp, int lastBossHp) 130 | { 131 | if (this.Current <= lastBossHp) return 1; //最後の1回 132 | return (int)Math.Ceiling((double)(this.Current - lastBossHp) / normalBossHp) + 1; 133 | } 134 | 135 | /// 136 | /// 輸送ゲージのS勝利時の残回数 137 | /// 138 | public int GetRemainingCountTransportS() 139 | { 140 | if (this.GaugeType != GaugeType.Transport) return -1; 141 | 142 | var capacity = KanColleClient.Current.Homeport.Organization.TransportationCapacity(); 143 | if (capacity.S == 0) return int.MaxValue; //ゲージ減らない 144 | return (int)Math.Ceiling((decimal)this.Current / capacity.S); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /EventMapHpViewer/ViewModels/Settings/TpSettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using EventMapHpViewer.Models; 2 | using EventMapHpViewer.Models.Settings; 3 | using Livet; 4 | using StatefulModel; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using MetroTrilithon.Mvvm; 11 | using System.Threading; 12 | using Grabacr07.KanColleWrapper; 13 | 14 | namespace EventMapHpViewer.ViewModels.Settings 15 | { 16 | public class TpSettingsViewModel: ViewModel 17 | { 18 | #region IsEnabled 19 | private bool _IsEnabled; 20 | public bool IsEnabled 21 | { 22 | get => this._IsEnabled; 23 | set 24 | { 25 | if (value == this._IsEnabled) 26 | return; 27 | this._IsEnabled = value; 28 | this.RaisePropertyChanged(); 29 | } 30 | } 31 | #endregion 32 | 33 | #region UseAutoCalcTpSettings 変更通知プロパティ 34 | public bool UseAutoCalcTpSettings 35 | { 36 | get => MapHpSettings.UseAutoCalcTpSettings.Value; 37 | set 38 | { 39 | if (MapHpSettings.UseAutoCalcTpSettings.Value == value) 40 | return; 41 | MapHpSettings.UseAutoCalcTpSettings.Value = value; 42 | this.RaisePropertyChanged(); 43 | } 44 | } 45 | #endregion 46 | 47 | #region TransportCapacity 変更通知プロパティ 48 | private TransportCapacity _TransportCapacity; 49 | 50 | public TransportCapacity TransportCapacity 51 | { 52 | get => this._TransportCapacity; 53 | set 54 | { 55 | if (this._TransportCapacity.Equals(value)) 56 | return; 57 | this._TransportCapacity = value; 58 | this.RaisePropertyChanged(); 59 | } 60 | } 61 | #endregion 62 | 63 | #region TransportCapacityS 変更通知プロパティ 64 | public decimal TransportCapacityS 65 | { 66 | get => MapHpSettings.TransportCapacityS.Value; 67 | set 68 | { 69 | if (MapHpSettings.TransportCapacityS.Value != value) 70 | { 71 | MapHpSettings.TransportCapacityS.Value = value; 72 | this.RaisePropertyChanged(); 73 | } 74 | this.TransportCapacity = new TransportCapacity(value); 75 | } 76 | } 77 | #endregion 78 | 79 | #region ShipTypeTpSettings 変更通知プロパティ 80 | private ReadOnlyNotifyChangedCollection _ShipTypeTpSettings; 81 | 82 | public ReadOnlyNotifyChangedCollection ShipTypeTpSettings 83 | { 84 | get => this._ShipTypeTpSettings; 85 | set 86 | { 87 | if (this._ShipTypeTpSettings == value) 88 | return; 89 | this._ShipTypeTpSettings = value; 90 | this.RaisePropertyChanged(); 91 | } 92 | } 93 | #endregion 94 | 95 | #region SlotItemTpSettings 変更通知プロパティ 96 | private ReadOnlyNotifyChangedCollection _SlotItemTpSettings; 97 | 98 | public ReadOnlyNotifyChangedCollection SlotItemTpSettings 99 | { 100 | get => this._SlotItemTpSettings; 101 | set 102 | { 103 | if (this._SlotItemTpSettings == value) 104 | return; 105 | this._SlotItemTpSettings = value; 106 | this.RaisePropertyChanged(); 107 | } 108 | } 109 | #endregion 110 | 111 | #region ShipTpSettings 変更通知プロパティ 112 | private ReadOnlyNotifyChangedCollection _ShipTpSettings; 113 | 114 | public ReadOnlyNotifyChangedCollection ShipTpSettings 115 | { 116 | get => this._ShipTpSettings; 117 | set 118 | { 119 | if (this._ShipTpSettings == value) 120 | return; 121 | this._ShipTpSettings = value; 122 | this.RaisePropertyChanged(); 123 | } 124 | } 125 | #endregion 126 | 127 | internal AutoCalcTpSettings Settings { get; } 128 | 129 | public TpSettingsViewModel() 130 | { 131 | this.Settings = AutoCalcTpSettings.FromSettings; 132 | 133 | this.Settings.Subscribe(nameof(AutoCalcTpSettings.ShipTypeTp), () => 134 | DispatcherHelper.UIDispatcher.Invoke(() => 135 | { 136 | this.ShipTypeTpSettings = this.Settings.ShipTypeTp 137 | .ToSyncedSynchronizationContextCollection(SynchronizationContext.Current) 138 | .ToSyncedSortedObservableCollection(x => x.TypeId * 10000 + x.SortId) 139 | .ToSyncedReadOnlyNotifyChangedCollection(); 140 | })) 141 | .AddTo(this); 142 | 143 | this.Settings.Subscribe(nameof(AutoCalcTpSettings.SlotItemTp), () => 144 | DispatcherHelper.UIDispatcher.Invoke(() => 145 | { 146 | this.SlotItemTpSettings = this.Settings.SlotItemTp 147 | .ToSyncedSynchronizationContextCollection(SynchronizationContext.Current) 148 | .ToSyncedSortedObservableCollection(x => x.TypeId * 10000 + x.SortId) 149 | .ToSyncedReadOnlyNotifyChangedCollection(); 150 | })) 151 | .AddTo(this); 152 | 153 | this.Settings.Subscribe(nameof(AutoCalcTpSettings.ShipTp), () => 154 | DispatcherHelper.UIDispatcher.Invoke(() => 155 | { 156 | this.ShipTpSettings = this.Settings.ShipTp 157 | .ToSyncedSynchronizationContextCollection(SynchronizationContext.Current) 158 | .ToSyncedSortedObservableCollection(x => x.TypeId * 10000 + x.SortId) 159 | .ToSyncedReadOnlyNotifyChangedCollection(); 160 | })) 161 | .AddTo(this); 162 | } 163 | 164 | public void Save() 165 | => this.Settings.Save(); 166 | 167 | public void Reset() 168 | => this.Settings.ResetAndSave(); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Settings/RemoteSettingsClient.cs: -------------------------------------------------------------------------------- 1 | using Codeplex.Data; 2 | using Grabacr07.KanColleWrapper; 3 | using Nekoxy; 4 | using System; 5 | using System.Collections.Concurrent; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using System.Linq; 9 | using System.Net; 10 | using System.Net.Http; 11 | using System.Reflection; 12 | using System.Text; 13 | using System.Text.RegularExpressions; 14 | using System.Threading; 15 | using System.Threading.Tasks; 16 | 17 | namespace EventMapHpViewer.Models.Settings 18 | { 19 | class RemoteSettingsClient 20 | { 21 | private HttpClient client; 22 | 23 | private readonly ConcurrentDictionary lastModified; 24 | 25 | private readonly ConcurrentDictionary caches; 26 | 27 | private TimeSpan cacheTtl; 28 | 29 | private bool updating; 30 | 31 | private static readonly object errorObject = new object(); 32 | 33 | public bool IsCacheError { get; set; } = true; 34 | 35 | #if DEBUG 36 | public RemoteSettingsClient() : this(TimeSpan.FromSeconds(10)) { } 37 | #else 38 | public RemoteSettingsClient() : this(TimeSpan.FromHours(1)) { } 39 | #endif 40 | 41 | public RemoteSettingsClient(TimeSpan cacheTtl) 42 | { 43 | this.lastModified = new ConcurrentDictionary(); 44 | this.caches = new ConcurrentDictionary(); 45 | this.cacheTtl = cacheTtl; 46 | } 47 | 48 | /// 49 | /// 艦これ戦術データ・リンクから設定情報を取得する。 50 | /// 取得できなかった場合は null を返す。 51 | /// 52 | /// 53 | /// 54 | /// 55 | public async Task GetSettings(string url) 56 | where T : class 57 | { 58 | DateTimeOffset lm; 59 | lock (this.lastModified) 60 | { 61 | while (this.updating) 62 | { 63 | Thread.Sleep(100); 64 | } 65 | 66 | lm = this.lastModified.GetOrAdd(url, DateTimeOffset.MinValue); 67 | 68 | if (DateTimeOffset.Now - lm < this.cacheTtl) 69 | { 70 | if (this.caches.TryGetValue(url, out var value)) 71 | { 72 | if (value is T) 73 | return (T)value; 74 | else if (value == errorObject) 75 | return null; 76 | } 77 | } 78 | this.updating = true; 79 | } 80 | 81 | if (this.client == null) 82 | { 83 | this.client = new HttpClient(GetProxyConfiguredHandler()); 84 | this.client.DefaultRequestHeaders 85 | .TryAddWithoutValidation("User-Agent", $"{MapHpViewer.title}/{MapHpViewer.version}"); 86 | } 87 | try 88 | { 89 | Debug.WriteLine($"MapHP - GET: {url}"); 90 | var response = await client.GetAsync(url); 91 | if (!response.IsSuccessStatusCode) 92 | { 93 | // 200 じゃなかった 94 | this.CacheError(url, lm); 95 | return null; 96 | } 97 | 98 | var json = await response.Content.ReadAsStringAsync(); 99 | T parsed = DynamicJson.Parse(json); 100 | this.lastModified.TryUpdate(url, DateTimeOffset.Now, lm); 101 | this.caches.AddOrUpdate(url, parsed, (_, __) => parsed); 102 | return parsed; 103 | } 104 | catch (HttpRequestException) 105 | { 106 | // HTTP リクエストに失敗した 107 | this.CacheError(url, lm); 108 | return null; 109 | } 110 | catch 111 | { 112 | // 不正な JSON 等 113 | this.CacheError(url, lm); 114 | return null; 115 | } 116 | finally 117 | { 118 | this.updating = false; 119 | } 120 | } 121 | 122 | private void CacheError(string url, DateTimeOffset lastModified) 123 | { 124 | if (!this.IsCacheError) 125 | return; 126 | this.lastModified.TryUpdate(url, DateTimeOffset.Now, lastModified); 127 | this.caches.AddOrUpdate(url, errorObject, (_, __) => errorObject); 128 | } 129 | 130 | public void CloseConnection() 131 | { 132 | this.client?.Dispose(); 133 | this.client = null; 134 | } 135 | 136 | /// 137 | /// 本体のプロキシ設定を組み込んだHttpClientHandlerを返す。 138 | /// 139 | /// 140 | private static HttpClientHandler GetProxyConfiguredHandler() 141 | { 142 | switch (HttpProxy.UpstreamProxyConfig.Type) 143 | { 144 | case ProxyConfigType.DirectAccess: 145 | return new HttpClientHandler 146 | { 147 | UseProxy = false 148 | }; 149 | case ProxyConfigType.SpecificProxy: 150 | var settings = KanColleClient.Current.Proxy.UpstreamProxySettings; 151 | var host = settings.IsUseHttpProxyForAllProtocols ? settings.HttpHost : settings.HttpsHost; 152 | var port = settings.IsUseHttpProxyForAllProtocols ? settings.HttpPort : settings.HttpsPort; 153 | if (string.IsNullOrWhiteSpace(host)) 154 | { 155 | return new HttpClientHandler { UseProxy = false }; 156 | } 157 | else 158 | { 159 | return new HttpClientHandler 160 | { 161 | UseProxy = true, 162 | Proxy = new WebProxy($"{host}:{port}"), 163 | }; 164 | } 165 | case ProxyConfigType.SystemProxy: 166 | return new HttpClientHandler(); 167 | default: 168 | return new HttpClientHandler(); 169 | } 170 | } 171 | 172 | public static string BuildBossSettingsUrl(string url, int id, int rank, int gaugeNum) 173 | { 174 | return BuildUrl(url, new Dictionary 175 | { 176 | { "version", $"{MapHpViewer.version}" }, 177 | { "mapId", id.ToString() }, 178 | { "rank", rank.ToString() }, 179 | { "gaugeNum", gaugeNum.ToString() }, 180 | }); 181 | } 182 | 183 | public static string BuildUrl(string url, IDictionary placeHolders) 184 | { 185 | if (placeHolders == null) 186 | return url; 187 | foreach(var placeHolder in placeHolders) 188 | { 189 | var regex = new Regex($"{{{placeHolder.Key}}}", RegexOptions.IgnoreCase | RegexOptions.Singleline); 190 | url = regex.Replace(url, placeHolder.Value); 191 | } 192 | return url; 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/MapInfoProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Reactive.Linq; 6 | using EventMapHpViewer.Models.Raw; 7 | using Grabacr07.KanColleWrapper; 8 | using Grabacr07.KanColleWrapper.Models; 9 | using Livet; 10 | using MetroTrilithon.Lifetime; 11 | using MetroTrilithon.Mvvm; 12 | 13 | namespace EventMapHpViewer.Models 14 | { 15 | public class MapInfoProxy : NotificationObject, IDisposableHolder 16 | { 17 | #region Maps変更通知プロパティ 18 | private Maps _Maps; 19 | 20 | public Maps Maps 21 | { 22 | get 23 | { return this._Maps; } 24 | set 25 | { 26 | if (this._Maps == value) 27 | return; 28 | this._Maps = value; 29 | this.RaisePropertyChanged(); 30 | } 31 | } 32 | #endregion 33 | 34 | public MapInfoProxy() 35 | { 36 | this.Maps = new Maps(); 37 | 38 | var proxy = KanColleClient.Current.Proxy; 39 | 40 | proxy.ApiSessionSource 41 | .Where(s => s.Request.PathAndQuery == "/kcsapi/api_start2/getData") 42 | .TryParse() 43 | .Subscribe(x => 44 | { 45 | Maps.MapAreas = new MasterTable(x.Data.api_mst_maparea.Select(m => new MapArea(m))); 46 | Maps.MapInfos = new MasterTable(x.Data.api_mst_mapinfo.Select(m => new MapInfo(m, Maps.MapAreas))); 47 | }) 48 | .AddTo(this); 49 | 50 | proxy.ApiSessionSource 51 | .Where(s => s.Request.PathAndQuery == "/kcsapi/api_get_member/mapinfo") 52 | .TryParse() 53 | .Subscribe(m => 54 | { 55 | Debug.WriteLine("MapInfoProxy - member_mapinfo"); 56 | this.Maps.MapList = this.CreateMapList(m.Data.api_map_info); 57 | this.RaisePropertyChanged(() => this.Maps); 58 | }) 59 | .AddTo(this); 60 | 61 | proxy.ApiSessionSource 62 | .Where(s => s.Request.PathAndQuery == "/kcsapi/api_req_map/select_eventmap_rank") 63 | .TryParse() 64 | .Subscribe(x => 65 | { 66 | Debug.WriteLine("MapInfoProxy - select_eventmap_rank"); 67 | this.Maps.MapList = this.UpdateRank(x); 68 | this.RaisePropertyChanged(() => this.Maps); 69 | }) 70 | .AddTo(this); 71 | 72 | 73 | proxy.ApiSessionSource 74 | .Where(x => x.Request.PathAndQuery == "/kcsapi/api_req_map/start") 75 | .TryParse() 76 | .Subscribe(x => 77 | { 78 | if (x.Data.api_eventmap == null) return; 79 | var targetMap = this.Maps.MapList 80 | .FirstOrDefault(m => m.Id.ToString() == x.Data.api_maparea_id.ToString() + x.Data.api_mapinfo_no.ToString()); 81 | if (targetMap?.Eventmap == null) return; 82 | 83 | if (targetMap.Eventmap.MaxMapHp.HasValue 84 | && targetMap.Eventmap.MaxMapHp != 9999) 85 | return; 86 | 87 | Debug.WriteLine("MapInfoProxy - map_start_next"); 88 | targetMap.Eventmap.NowMapHp = x.Data.api_eventmap.api_now_maphp; 89 | targetMap.Eventmap.MaxMapHp = x.Data.api_eventmap.api_max_maphp; 90 | this.RaisePropertyChanged(() => this.Maps); 91 | }) 92 | .AddTo(this); 93 | } 94 | 95 | private MapData[] CreateMapList(IEnumerable maps) 96 | { 97 | return maps 98 | .Select(x => new MapData 99 | { 100 | IsCleared = x.api_defeat_count.HasValue ? 0 : x.api_cleared, 101 | DefeatCount = x.api_defeat_count ?? 0, 102 | RequiredDefeatCount = x.api_required_defeat_count ?? 0, 103 | Id = x.api_id, 104 | Eventmap = x.api_eventmap != null 105 | ? new Eventmap 106 | { 107 | MaxMapHp = x.api_eventmap.api_max_maphp, 108 | NowMapHp = x.api_eventmap.api_now_maphp, 109 | SelectedRank = (Rank) x.api_eventmap.api_selected_rank, 110 | State = x.api_eventmap.api_state, 111 | } 112 | : null, 113 | GaugeType = (GaugeType)(x.api_gauge_type ?? 0), 114 | GaugeNum = x.api_gauge_num, 115 | }).ToArray(); 116 | } 117 | 118 | private MapData[] UpdateRank(SvData data) 119 | { 120 | var rank = 0; 121 | int.TryParse(data.Request["api_rank"], out rank); 122 | var areaId = data.Request["api_maparea_id"]; 123 | var mapNo = data.Request["api_map_no"]; 124 | 125 | 126 | var list = this.Maps.MapList; 127 | var targetMap = list.FirstOrDefault(m => m.Id.ToString() == areaId + mapNo); 128 | if (targetMap?.Eventmap == null) return list; 129 | 130 | targetMap.Eventmap.SelectedRank = (Rank) rank; 131 | if(int.TryParse(data.Data.api_maphp.api_gauge_type, out var gaugeType)) 132 | targetMap.GaugeType = (GaugeType) gaugeType; 133 | targetMap.Eventmap.MaxMapHp = data.Data.api_maphp.api_max_maphp; 134 | targetMap.Eventmap.NowMapHp = data.Data.api_maphp.api_now_maphp; 135 | return list; 136 | } 137 | 138 | ICollection IDisposableHolder.CompositeDisposable { get; } 139 | = new ObservableSynchronizedCollection(); 140 | 141 | #region IDisposable Support 142 | private bool disposedValue = false; // 重複する呼び出しを検出するには 143 | 144 | protected virtual void Dispose(bool disposing) 145 | { 146 | if (!disposedValue) 147 | { 148 | if (disposing) 149 | { 150 | // TODO: マネージド状態を破棄します (マネージド オブジェクト)。 151 | lock (this) 152 | { 153 | foreach (var disposable in ((IDisposableHolder)this).CompositeDisposable) 154 | { 155 | disposable.Dispose(); 156 | } 157 | } 158 | } 159 | 160 | // TODO: アンマネージド リソース (アンマネージド オブジェクト) を解放し、下のファイナライザーをオーバーライドします。 161 | // TODO: 大きなフィールドを null に設定します。 162 | 163 | disposedValue = true; 164 | } 165 | } 166 | 167 | // TODO: 上の Dispose(bool disposing) にアンマネージド リソースを解放するコードが含まれる場合にのみ、ファイナライザーをオーバーライドします。 168 | // ~MapInfoProxy() { 169 | // // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。 170 | // Dispose(false); 171 | // } 172 | 173 | // このコードは、破棄可能なパターンを正しく実装できるように追加されました。 174 | public void Dispose() 175 | { 176 | // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。 177 | Dispose(true); 178 | // TODO: 上のファイナライザーがオーバーライドされる場合は、次の行のコメントを解除してください。 179 | // GC.SuppressFinalize(this); 180 | } 181 | #endregion 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/visualstudio 3 | 4 | ### VisualStudio ### 5 | ## Ignore Visual Studio temporary files, build results, and 6 | ## files generated by popular Visual Studio add-ons. 7 | ## 8 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 9 | 10 | # User-specific files 11 | *.suo 12 | *.user 13 | *.userosscache 14 | *.sln.docstates 15 | 16 | # User-specific files (MonoDevelop/Xamarin Studio) 17 | *.userprefs 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | bld/ 27 | [Bb]in/ 28 | [Oo]bj/ 29 | [Ll]og/ 30 | 31 | # Visual Studio 2015/2017 cache/options directory 32 | .vs/ 33 | # Uncomment if you have tasks that create the project's static files in wwwroot 34 | #wwwroot/ 35 | 36 | # Visual Studio 2017 auto generated files 37 | Generated\ Files/ 38 | 39 | # MSTest test Results 40 | [Tt]est[Rr]esult*/ 41 | [Bb]uild[Ll]og.* 42 | 43 | # NUNIT 44 | *.VisualState.xml 45 | TestResult.xml 46 | 47 | # Build Results of an ATL Project 48 | [Dd]ebugPS/ 49 | [Rr]eleasePS/ 50 | dlldata.c 51 | 52 | # Benchmark Results 53 | BenchmarkDotNet.Artifacts/ 54 | 55 | # .NET Core 56 | project.lock.json 57 | project.fragment.lock.json 58 | artifacts/ 59 | 60 | # StyleCop 61 | StyleCopReport.xml 62 | 63 | # Files built by Visual Studio 64 | *_i.c 65 | *_p.c 66 | *_h.h 67 | *.ilk 68 | *.meta 69 | *.obj 70 | *.iobj 71 | *.pch 72 | *.pdb 73 | *.ipdb 74 | *.pgc 75 | *.pgd 76 | *.rsp 77 | *.sbr 78 | *.tlb 79 | *.tli 80 | *.tlh 81 | *.tmp 82 | *.tmp_proj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | 259 | # Microsoft Fakes 260 | FakesAssemblies/ 261 | 262 | # GhostDoc plugin setting file 263 | *.GhostDoc.xml 264 | 265 | # Node.js Tools for Visual Studio 266 | .ntvs_analysis.dat 267 | node_modules/ 268 | 269 | # Visual Studio 6 build log 270 | *.plg 271 | 272 | # Visual Studio 6 workspace options file 273 | *.opt 274 | 275 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 276 | *.vbw 277 | 278 | # Visual Studio LightSwitch build output 279 | **/*.HTMLClient/GeneratedArtifacts 280 | **/*.DesktopClient/GeneratedArtifacts 281 | **/*.DesktopClient/ModelManifest.xml 282 | **/*.Server/GeneratedArtifacts 283 | **/*.Server/ModelManifest.xml 284 | _Pvt_Extensions 285 | 286 | # Paket dependency manager 287 | .paket/paket.exe 288 | paket-files/ 289 | 290 | # FAKE - F# Make 291 | .fake/ 292 | 293 | # JetBrains Rider 294 | .idea/ 295 | *.sln.iml 296 | 297 | # CodeRush 298 | .cr/ 299 | 300 | # Python Tools for Visual Studio (PTVS) 301 | __pycache__/ 302 | *.pyc 303 | 304 | # Cake - Uncomment if you are using it 305 | # tools/** 306 | # !tools/packages.config 307 | 308 | # Tabs Studio 309 | *.tss 310 | 311 | # Telerik's JustMock configuration file 312 | *.jmconfig 313 | 314 | # BizTalk build output 315 | *.btp.cs 316 | *.btm.cs 317 | *.odx.cs 318 | *.xsd.cs 319 | 320 | # OpenCover UI analysis results 321 | OpenCover/ 322 | 323 | # Azure Stream Analytics local run output 324 | ASALocalRun/ 325 | 326 | # MSBuild Binary and Structured Log 327 | *.binlog 328 | 329 | # NVidia Nsight GPU debugger configuration file 330 | *.nvuser 331 | 332 | # MFractors (Xamarin productivity tool) working folder 333 | .mfractor/ 334 | 335 | # Local History for Visual Studio 336 | .localhistory/ 337 | 338 | 339 | # End of https://www.gitignore.io/api/visualstudio -------------------------------------------------------------------------------- /EventMapHpViewer/ViewModels/ToolViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EventMapHpViewer.Models; 3 | using Livet; 4 | using Livet.EventListeners; 5 | using Grabacr07.KanColleWrapper; 6 | using MetroTrilithon.Mvvm; 7 | using System.Collections.Generic; 8 | using Grabacr07.KanColleWrapper.Models; 9 | using System; 10 | using System.Reactive.Linq; 11 | using EventMapHpViewer.Models.Raw; 12 | using System.Diagnostics; 13 | using EventMapHpViewer.Models.Settings; 14 | 15 | namespace EventMapHpViewer.ViewModels 16 | { 17 | public class ToolViewModel : ViewModel 18 | { 19 | private readonly MapInfoProxy mapInfoProxy; 20 | 21 | public ToolViewModel(MapInfoProxy proxy) 22 | { 23 | this.mapInfoProxy = proxy; 24 | this.CompositeDisposable.Add(proxy); 25 | 26 | if (this.mapInfoProxy == null) return; 27 | 28 | this.mapInfoProxy.Subscribe( 29 | nameof(MapInfoProxy.Maps), 30 | () => 31 | { 32 | if (this.mapInfoProxy?.Maps?.MapList == null) return; 33 | // 雑 34 | this.Maps = this.mapInfoProxy.Maps.MapList 35 | .OrderBy(x => x.Id) 36 | .Select(x => new MapViewModel(x)) 37 | .Where(x => !x.IsCleared) 38 | .ToArray(); 39 | this.IsNoMap = !this.Maps.Any(); 40 | }, false) 41 | .AddTo(this); 42 | 43 | KanColleClient.Current 44 | .Subscribe(nameof(KanColleClient.IsStarted), Initialize, false) 45 | .AddTo(this); 46 | 47 | MapHpSettings.UseLocalBossSettings.Subscribe(_ => this.UpdateRemainingCount()).AddTo(this); 48 | MapHpSettings.BossSettings.Subscribe(_ => this.UpdateRemainingCount()).AddTo(this); 49 | // RemoteBossSettingsUrl は文字入力の度にリクエスト飛ぶようになるのは現実的ではないので、変更検知しない 50 | //MapHpSettings.RemoteBossSettingsUrl.Subscribe(_ => this.UpdateRemainingCount()).AddTo(this); 51 | 52 | MapHpSettings.UseAutoCalcTpSettings.Subscribe(_ => this.UpdateTransportCapacity()).AddTo(this); 53 | MapHpSettings.TransportCapacityS.Subscribe(_ => this.UpdateTransportCapacity()).AddTo(this); 54 | MapHpSettings.ShipTypeTpSettings.Subscribe(_ => this.UpdateTransportCapacity()).AddTo(this); 55 | MapHpSettings.SlotItemTpSettings.Subscribe(_ => this.UpdateTransportCapacity()).AddTo(this); 56 | MapHpSettings.ShipTpSettings.Subscribe(_ => this.UpdateTransportCapacity()).AddTo(this); 57 | } 58 | 59 | public void Initialize() 60 | { 61 | KanColleClient.Current.Homeport.Organization 62 | .Subscribe(nameof(Organization.Fleets), this.UpdateFleets, false) 63 | .Subscribe(nameof(Organization.Combined), this.UpdateTransportCapacity, false) 64 | .Subscribe(nameof(Organization.Ships), () => this.handledShips.Clear(), false) 65 | .AddTo(this); 66 | KanColleClient.Current.Proxy.ApiSessionSource 67 | .Where(s => s.Request.PathAndQuery == "/kcsapi/api_req_map/next") 68 | .TryParse() 69 | .Subscribe(x => 70 | { 71 | if (x.Data.api_event_id == 9) 72 | { 73 | Debug.WriteLine("ToolViewModel: fixedTransportCapacity = true"); 74 | this.fixedTransportCapacity = true; 75 | } 76 | }) 77 | .AddTo(this); 78 | KanColleClient.Current.Proxy.api_port 79 | .Subscribe(_ => 80 | { 81 | if (fixedTransportCapacity) 82 | { 83 | Debug.WriteLine("ToolViewModel: fixedTransportCapacity = false"); 84 | this.fixedTransportCapacity = false; 85 | } 86 | this.UpdateTransportCapacity(); 87 | }) 88 | .AddTo(this); 89 | } 90 | 91 | #region Maps変更通知プロパティ 92 | private MapViewModel[] _Maps; 93 | 94 | public MapViewModel[] Maps 95 | { 96 | get 97 | { return this._Maps; } 98 | set 99 | { 100 | if (this._Maps == value) 101 | return; 102 | this._Maps = value; 103 | this.RaisePropertyChanged(); 104 | this.RaisePropertyChanged(nameof(this.ExistsTransportGauge)); 105 | } 106 | } 107 | #endregion 108 | 109 | 110 | #region IsNoMap変更通知プロパティ 111 | private bool _IsNoMap; 112 | 113 | public bool IsNoMap 114 | { 115 | get 116 | { return this._IsNoMap; } 117 | set 118 | { 119 | if (this._IsNoMap == value) 120 | return; 121 | this._IsNoMap = value; 122 | this.RaisePropertyChanged(); 123 | } 124 | } 125 | #endregion 126 | 127 | 128 | #region TransportCapacity 変更通知プロパティ 129 | private TransportCapacity _TransportCapacity; 130 | 131 | public TransportCapacity TransportCapacity 132 | { 133 | get 134 | { return this._TransportCapacity; } 135 | set 136 | { 137 | if (this._TransportCapacity.Equals(value)) 138 | return; 139 | this._TransportCapacity = value; 140 | this.RaisePropertyChanged(); 141 | } 142 | } 143 | #endregion 144 | 145 | public bool ExistsTransportGauge 146 | => this.Maps?.Any(x => x.GaugeType == GaugeType.Transport) ?? false; 147 | 148 | private readonly HashSet handledShips = new HashSet(); 149 | 150 | private readonly List fleetHandlers = new List(); 151 | 152 | private bool fixedTransportCapacity; 153 | 154 | private void UpdateFleets() 155 | { 156 | foreach (var handler in fleetHandlers) 157 | { 158 | handler.Dispose(); 159 | } 160 | this.fleetHandlers.Clear(); 161 | foreach (var fleet in KanColleClient.Current.Homeport.Organization.Fleets.Values) 162 | { 163 | this.fleetHandlers.Add(fleet.Subscribe(nameof(fleet.Ships), this.UpdateTransportCapacity, false)); 164 | foreach (var ship in fleet.Ships) 165 | { 166 | if (this.handledShips.Contains(ship)) return; 167 | this.fleetHandlers.Add(ship.Subscribe(nameof(ship.Slots), this.UpdateTransportCapacity, false)); 168 | this.fleetHandlers.Add(ship.Subscribe(nameof(ship.Situation), this.UpdateTransportCapacity, false)); 169 | this.handledShips.Add(ship); 170 | } 171 | } 172 | } 173 | 174 | private void UpdateTransportCapacity() 175 | { 176 | if (this.fixedTransportCapacity) return; // 揚陸地点到達後は更新しない 177 | 178 | if (KanColleClient.Current.Homeport?.Organization?.Fleets.Any() != true) return; 179 | 180 | Debug.WriteLine(nameof(this.UpdateTransportCapacity)); 181 | this.TransportCapacity = KanColleClient.Current.Homeport.Organization.TransportationCapacity(); 182 | this.UpdateRemainingCount(); 183 | } 184 | 185 | private void UpdateRemainingCount() 186 | { 187 | if (this.fixedTransportCapacity) return; // 揚陸地点到達後は更新しない 188 | 189 | if (this.Maps == null) return; 190 | foreach (var map in this.Maps) 191 | { 192 | map.UpdateRemainingCount(); 193 | } 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 31 | 32 | 33 | 34 | 35 | $(SolutionDir).nuget 36 | 37 | 38 | 39 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config 40 | $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config 41 | 42 | 43 | 44 | $(MSBuildProjectDirectory)\packages.config 45 | $(PackagesProjectConfig) 46 | 47 | 48 | 49 | 50 | $(NuGetToolsPath)\NuGet.exe 51 | @(PackageSource) 52 | 53 | "$(NuGetExePath)" 54 | mono --runtime=v4.0.30319 "$(NuGetExePath)" 55 | 56 | $(TargetDir.Trim('\\')) 57 | 58 | -RequireConsent 59 | -NonInteractive 60 | 61 | "$(SolutionDir) " 62 | "$(SolutionDir)" 63 | 64 | 65 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) 66 | $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 67 | 68 | 69 | 70 | RestorePackages; 71 | $(BuildDependsOn); 72 | 73 | 74 | 75 | 76 | $(BuildDependsOn); 77 | BuildPackage; 78 | 79 | 80 | 81 | 82 | 83 | 84 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 99 | 100 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /licenses/LGPL.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /EventMapHpViewer/Models/Settings/AutoCalcTpSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Codeplex.Data; 9 | using Grabacr07.KanColleWrapper; 10 | using Grabacr07.KanColleWrapper.Models; 11 | using Grabacr07.KanColleWrapper.Models.Raw; 12 | using StatefulModel; 13 | using MetroTrilithon.Mvvm; 14 | 15 | namespace EventMapHpViewer.Models.Settings 16 | { 17 | class AutoCalcTpSettings : Livet.NotificationObject 18 | { 19 | #region ShipTypeTp 20 | 21 | private ObservableSynchronizedCollection _ShipTypeTp; 22 | public ObservableSynchronizedCollection ShipTypeTp 23 | { 24 | get => this._ShipTypeTp; 25 | private set 26 | { 27 | if (this._ShipTypeTp == value) 28 | return; 29 | this._ShipTypeTp = value; 30 | this.RaisePropertyChanged(); 31 | } 32 | } 33 | 34 | #endregion 35 | 36 | #region SlotItemTp 37 | 38 | private ObservableSynchronizedCollection _SlotItemTp; 39 | public ObservableSynchronizedCollection SlotItemTp 40 | { 41 | get => this._SlotItemTp; 42 | private set 43 | { 44 | if (this._SlotItemTp == value) 45 | return; 46 | this._SlotItemTp = value; 47 | this.RaisePropertyChanged(); 48 | } 49 | } 50 | 51 | #endregion 52 | 53 | #region ShipTp 54 | 55 | private ObservableSynchronizedCollection _ShipTp; 56 | public ObservableSynchronizedCollection ShipTp 57 | { 58 | get => this._ShipTp; 59 | private set 60 | { 61 | if (this._ShipTp == value) 62 | return; 63 | this._ShipTp = value; 64 | this.RaisePropertyChanged(); 65 | } 66 | } 67 | 68 | #endregion 69 | 70 | public AutoCalcTpSettings() 71 | { 72 | this.ShipTypeTp = Default.ShipTypeTp; 73 | this.SlotItemTp = Default.SlotItemTp; 74 | this.ShipTp = Default.ShipTp; 75 | } 76 | 77 | private AutoCalcTpSettings(string stypeTp, string slotitemTp, string shipTp) 78 | { 79 | try { this.ShipTypeTp = DynamicJson.Parse(stypeTp); } 80 | catch { this.ShipTypeTp = Default.ShipTypeTp; } 81 | 82 | try { this.SlotItemTp = DynamicJson.Parse(slotitemTp); } 83 | catch { this.SlotItemTp = Default.SlotItemTp; } 84 | 85 | try { this.ShipTp = DynamicJson.Parse(shipTp); } 86 | catch { this.ShipTp = Default.ShipTp; } 87 | } 88 | 89 | private AutoCalcTpSettings(IEnumerable stypeTp, IEnumerable slotitemTp, IEnumerable shipTp) 90 | { 91 | this.ShipTypeTp = new ObservableSynchronizedCollection(new ObservableCollection(stypeTp)); 92 | this.SlotItemTp = new ObservableSynchronizedCollection(new ObservableCollection(slotitemTp)); 93 | this.ShipTp = new ObservableSynchronizedCollection(new ObservableCollection(shipTp)); 94 | } 95 | 96 | public void RestoreDefault() 97 | { 98 | this.ShipTypeTp = Default.ShipTypeTp; 99 | this.SlotItemTp = Default.SlotItemTp; 100 | this.ShipTp = Default.ShipTp; 101 | this.UpdateFromMaster(); 102 | } 103 | 104 | public void UpdateFromMaster() 105 | { 106 | if (!KanColleClient.Current.IsStarted) return; 107 | 108 | var master = KanColleClient.Current.Master; 109 | 110 | this.ShipTypeTp = master.ShipTypes.UpdateSettings(this.ShipTypeTp, 111 | x => true, 112 | x => new TpSetting(x.Id, x.SortNumber, x.Name)); 113 | 114 | this.SlotItemTp = master.SlotItems.UpdateSettings(this.SlotItemTp, 115 | x => x.RawData.api_sortno != 0, 116 | x => new TpSetting(x.Id, x.RawData.api_sortno, x.Name, 0, x.EquipType.Id, x.EquipType.Name)); 117 | 118 | this.ShipTp = master.Ships.UpdateSettings(this.ShipTp, 119 | x => x.SortId != 0, 120 | x => new TpSetting(x.Id, x.SortId, x.Name, 0, x.ShipType.Id, x.ShipType.Name)); 121 | 122 | this.Save(); 123 | } 124 | 125 | public static AutoCalcTpSettings Default { get; } = CreateDefault(); 126 | 127 | private static AutoCalcTpSettings CreateDefault() 128 | { 129 | var stypTp = new[] 130 | { 131 | new TpSetting(2, 2, "駆逐艦", 5), 132 | new TpSetting(3, 3, "軽巡洋艦", 2), 133 | new TpSetting(10, 10, "航空戦艦", 7), 134 | new TpSetting(16, 16, "水上機母艦", 9), 135 | new TpSetting(14, 14, "潜水空母", 1), 136 | new TpSetting(21, 21, "練習巡洋艦", 6), 137 | new TpSetting(6, 6, "航空巡洋艦", 4), 138 | new TpSetting(22, 22, "補給艦", 15), 139 | new TpSetting(17, 17, "揚陸艦", 12), 140 | new TpSetting(20, 20, "潜水母艦", 7), 141 | }; 142 | 143 | var slotitemTp = new[] 144 | { 145 | new TpSetting(75, 75, "ドラム缶(輸送用)", 5), 146 | new TpSetting(68, 68, "大発動艇", 8), 147 | new TpSetting(193, 193, "特大発動艇", 8), 148 | new TpSetting(166, 166, "大発動艇(八九式中戦車&陸戦隊)", 8), 149 | new TpSetting(230, 230, "特大発動艇+戦車第11連隊", 8), 150 | new TpSetting(355, 355, "M4A1 DD", 8), 151 | new TpSetting(167, 167, "特二式内火艇", 2), 152 | new TpSetting(145, 145, "戦闘糧食", 1), 153 | new TpSetting(150, 150, "秋刀魚の缶詰", 1), 154 | new TpSetting(241, 241, "戦闘糧食(特別なおにぎり)", 1), 155 | }; 156 | 157 | var shipTp = new[] 158 | { 159 | new TpSetting(487, 287, "鬼怒改二", 8), 160 | }; 161 | 162 | return new AutoCalcTpSettings(stypTp, slotitemTp, shipTp); 163 | } 164 | 165 | public static AutoCalcTpSettings FromSettings 166 | { 167 | get => new AutoCalcTpSettings( 168 | MapHpSettings.ShipTypeTpSettings?.Value, 169 | MapHpSettings.SlotItemTpSettings?.Value, 170 | MapHpSettings.ShipTpSettings?.Value); 171 | } 172 | 173 | } 174 | 175 | static class AutoCalcTpSettingsExtensions 176 | { 177 | public static void Save(this AutoCalcTpSettings settings) 178 | { 179 | if (settings.ShipTypeTp.Any()) 180 | MapHpSettings.ShipTypeTpSettings.Value = DynamicJson.Serialize(settings.ShipTypeTp); 181 | if (settings.SlotItemTp.Any()) 182 | MapHpSettings.SlotItemTpSettings.Value = DynamicJson.Serialize(settings.SlotItemTp); 183 | if (settings.ShipTp.Any()) 184 | MapHpSettings.ShipTpSettings.Value = DynamicJson.Serialize(settings.ShipTp); 185 | } 186 | 187 | public static void ResetAndSave(this AutoCalcTpSettings settings) 188 | { 189 | MapHpSettings.ShipTypeTpSettings?.Reset(); 190 | MapHpSettings.SlotItemTpSettings?.Reset(); 191 | MapHpSettings.ShipTpSettings?.Reset(); 192 | settings.RestoreDefault(); 193 | } 194 | 195 | public static ObservableSynchronizedCollection UpdateSettings(this MasterTable master, 196 | IEnumerable oldSettings, 197 | Func filter, 198 | Func selector) 199 | where T : class, IIdentifiable 200 | { 201 | var newTps = master 202 | .Select(x => x.Value) 203 | .Where(filter) 204 | .Select(selector) 205 | .ToDictionary(x => x.Id); 206 | foreach (var oldTp in oldSettings) 207 | { 208 | if (newTps.Any(x => x.Key == oldTp.Id)) 209 | { 210 | newTps[oldTp.Id].Tp = oldTp.Tp; 211 | } 212 | else 213 | { 214 | newTps.Add(oldTp.Id, oldTp); 215 | } 216 | } 217 | return new ObservableSynchronizedCollection(new ObservableCollection(newTps.Select(x => x.Value))); 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Settings/TpSettingsListView.xaml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | 30 | 33 | 34 | 38 | 75 | 76 | 77 | 78 | 80 | 81 | 82 | 85 | 86 | 87 | 88 | 90 | 91 | 92 | 95 | 96 | 97 | 98 | 100 | 101 | 102 | 105 | 106 | 107 | 108 | 110 | 111 | 112 | 115 | 116 | 117 | 118 | 120 | 121 | 122 | 123 | 124 | 133 | 134 | 135 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Settings/TpSettings.xaml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 39 | 40 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 52 | 53 | 56 | 61 | 63 | 65 | 66 | 67 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 81 | 82 | 83 | 84 | 88 | 89 | 90 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 102 | 103 | 105 | 106 | 107 | 109 | 110 | 116 | 117 | 118 | 119 | 121 | 122 | 128 | 129 | 130 | 131 | 133 | 134 | 140 | 141 | 142 | 143 | 151 | 152 | 153 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /EventMapHpViewer/ViewModels/Settings/BossSettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using EventMapHpViewer.Models.Settings; 2 | using Grabacr07.KanColleWrapper; 3 | using Livet; 4 | using StatefulModel; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using MetroTrilithon.Mvvm; 11 | using System.Threading; 12 | using System.Runtime.CompilerServices; 13 | 14 | namespace EventMapHpViewer.ViewModels.Settings 15 | { 16 | public class BossSettingsViewModel: ViewModel 17 | { 18 | #region IsEnabled 19 | private bool _IsEnabled; 20 | public bool IsEnabled 21 | { 22 | get => this._IsEnabled; 23 | set 24 | { 25 | if (value == this._IsEnabled) 26 | return; 27 | this._IsEnabled = value; 28 | this.RaisePropertyChanged(); 29 | } 30 | } 31 | #endregion 32 | 33 | #region UseLocalBossSettings 34 | public bool UseLocalBossSettings 35 | { 36 | get => MapHpSettings.UseLocalBossSettings.Value; 37 | set 38 | { 39 | if (value == MapHpSettings.UseLocalBossSettings.Value) 40 | return; 41 | MapHpSettings.UseLocalBossSettings.Value = value; 42 | this.RaisePropertyChanged(); 43 | } 44 | } 45 | #endregion 46 | 47 | #region MapId 48 | private int _MapId; 49 | public int MapId 50 | { 51 | get => this._MapId; 52 | set 53 | { 54 | if (value == this._MapId) 55 | return; 56 | this._MapId = value; 57 | this.RaisePropertyChanged(); 58 | } 59 | } 60 | #endregion 61 | 62 | #region MapItemsSource 63 | private IEnumerable> _MapItemsSource; 64 | public IEnumerable> MapItemsSource 65 | { 66 | get => this._MapItemsSource; 67 | set 68 | { 69 | if (value == this._MapItemsSource) 70 | return; 71 | this._MapItemsSource = value; 72 | this.RaisePropertyChanged(); 73 | } 74 | } 75 | #endregion 76 | 77 | #region Rank 78 | private int _Rank; 79 | public int Rank 80 | { 81 | get => this._Rank; 82 | set 83 | { 84 | if (value == this._Rank) 85 | return; 86 | this._Rank = value; 87 | this.RaisePropertyChanged(); 88 | } 89 | } 90 | #endregion 91 | 92 | #region RankItemsSource 93 | 94 | public IEnumerable> RankItemsSource { get; } 95 | = Enum.GetValues(typeof(Models.Rank)) 96 | .Cast() 97 | .Select(x => new KeyValuePair((int)x, x.ToString())) 98 | .ToArray(); 99 | 100 | #endregion 101 | 102 | #region GaugeNum 103 | private string _GaugeNum; 104 | public string GaugeNum 105 | { 106 | get => this._GaugeNum; 107 | set 108 | { 109 | if (value == this._GaugeNum) 110 | return; 111 | this._GaugeNum = value; 112 | this.RaisePropertyChanged(); 113 | } 114 | } 115 | #endregion 116 | 117 | #region BossHP 118 | private int _BossHP; 119 | public int BossHP 120 | { 121 | get => this._BossHP; 122 | set 123 | { 124 | if (value == this._BossHP) 125 | return; 126 | this._BossHP = value; 127 | this.RaisePropertyChanged(); 128 | } 129 | } 130 | #endregion 131 | 132 | #region IsLast 133 | private bool _IsLast; 134 | public bool IsLast 135 | { 136 | get => this._IsLast; 137 | set 138 | { 139 | if (value == this._IsLast) 140 | return; 141 | this._IsLast = value; 142 | this.RaisePropertyChanged(); 143 | } 144 | } 145 | #endregion 146 | 147 | #region IsAddEnabled 148 | public bool IsAddEnabled 149 | { 150 | get => !this.Settings.List.Any( 151 | x => x.MapId == this.MapId 152 | && x.Rank == this.Rank 153 | && x.GaugeNum.ToString() == this.GaugeNum 154 | && x.BossHP == this.BossHP 155 | && x.IsLast == this.IsLast 156 | ) 157 | && this.MapId != default 158 | && this.Rank != default 159 | // && this.GaugeNum != default // 空もありとする 160 | && this.BossHP != default; 161 | } 162 | #endregion 163 | 164 | #region IsModifyRemoveEnabled 165 | public bool IsModifyRemoveEnabled 166 | { 167 | get => this.SelectedBossSetting != null; 168 | } 169 | #endregion 170 | 171 | #region SelectedBossSetting 172 | private BossSetting _SelectedBossSetting; 173 | public BossSetting SelectedBossSetting 174 | { 175 | get => this._SelectedBossSetting; 176 | set 177 | { 178 | this._SelectedBossSetting = value; 179 | if(value != null) 180 | { 181 | this.MapId = value.MapId; 182 | this.Rank = value.Rank; 183 | this.GaugeNum = value.GaugeNum.ToString(); 184 | this.BossHP = value.BossHP; 185 | this.IsLast = value.IsLast; 186 | } 187 | else 188 | { 189 | this.MapId = default; 190 | this.Rank = default; 191 | this.GaugeNum = default; 192 | this.BossHP = default; 193 | this.IsLast = default; 194 | } 195 | this.RaisePropertyChanged(); 196 | } 197 | } 198 | #endregion 199 | 200 | #region BossSettings 201 | private ReadOnlyNotifyChangedCollection _BossSettings; 202 | public ReadOnlyNotifyChangedCollection BossSettings 203 | { 204 | get => this._BossSettings; 205 | set 206 | { 207 | this._BossSettings = value; 208 | this.RaisePropertyChanged(); 209 | } 210 | } 211 | #endregion 212 | 213 | #region RemoteBossSettingsUrl 214 | public string RemoteBossSettingsUrl 215 | { 216 | get => MapHpSettings.RemoteBossSettingsUrl.Value; 217 | set 218 | { 219 | if (MapHpSettings.RemoteBossSettingsUrl.Value == value) 220 | return; 221 | if (value == null) 222 | MapHpSettings.RemoteBossSettingsUrl.Reset(); 223 | else 224 | MapHpSettings.RemoteBossSettingsUrl.Value = value; 225 | this.RaisePropertyChanged(); 226 | } 227 | } 228 | #endregion 229 | 230 | private BossSettingsWrapper Settings { get; } 231 | 232 | public BossSettingsViewModel() 233 | { 234 | this.Settings = BossSettingsWrapper.FromSettings; 235 | 236 | this.BossSettings = this.Settings.List 237 | .ToSyncedSortedObservableCollection(x => $"{x.MapId:D4}{x.Rank:D2}{x.GaugeNum ?? 0:D2}{(x.IsLast ? 1 : 0)}{x.BossHP:D4}") 238 | .ToSyncedSynchronizationContextCollection(SynchronizationContext.Current) 239 | .ToSyncedReadOnlyNotifyChangedCollection(); 240 | } 241 | 242 | public void Add() 243 | { 244 | var newValue = new BossSetting 245 | { 246 | MapId = this.MapId, 247 | Rank = this.Rank, 248 | GaugeNum = int.TryParse(this.GaugeNum, out var num) ? num : (int?)null, 249 | BossHP = this.BossHP, 250 | IsLast = this.IsLast 251 | }; 252 | this.Settings.List.Add(newValue); 253 | this.Settings.Save(); 254 | this.SelectedBossSetting = newValue; 255 | this.UpdateButtonState(); 256 | } 257 | 258 | public void Modify() 259 | { 260 | this.Settings.List.Remove(this.SelectedBossSetting); 261 | this.Add(); 262 | } 263 | 264 | public void Remove() 265 | { 266 | this.Settings.List.Remove(this.SelectedBossSetting); 267 | this.Settings.Save(); 268 | this.UpdateButtonState(); 269 | } 270 | 271 | public void RestoreDefaultRemoteBossSettingsUrl() 272 | { 273 | this.RemoteBossSettingsUrl = MapHpSettings.RemoteBossSettingsUrl?.Default; 274 | } 275 | 276 | private void UpdateButtonState() 277 | { 278 | this.RaisePropertyChanged(nameof(this.IsAddEnabled)); 279 | this.RaisePropertyChanged(nameof(this.IsModifyRemoveEnabled)); 280 | } 281 | 282 | protected override void RaisePropertyChanged([CallerMemberName] string propertyName = "") 283 | { 284 | base.RaisePropertyChanged(propertyName); 285 | 286 | if(propertyName != nameof(this.IsAddEnabled) 287 | && propertyName != nameof(this.IsModifyRemoveEnabled)) 288 | this.UpdateButtonState(); 289 | } 290 | } 291 | } 292 | -------------------------------------------------------------------------------- /EventMapHpViewer/SampleData/ToolViewModelSampleData.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 47 | 48 | 49 | 50 | 51 | 67 | 68 | 69 | 70 | 71 | 88 | 89 | 90 | 91 | 92 | 109 | 110 | 111 | 112 | 113 | 131 | 132 | 133 | 134 | 135 | 153 | 154 | 155 | 156 | 157 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /licenses/Apache.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /EventMapHpViewer/ViewModels/MapViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Windows; 4 | using System.Windows.Media; 5 | using EventMapHpViewer.Models; 6 | using EventMapHpViewer.Models.Settings; 7 | using Livet; 8 | using MetroTrilithon.Mvvm; 9 | 10 | namespace EventMapHpViewer.ViewModels 11 | { 12 | public class MapViewModel : ViewModel 13 | { 14 | 15 | private static readonly SolidColorBrush red; 16 | private static readonly SolidColorBrush green; 17 | 18 | static MapViewModel() 19 | { 20 | red = new SolidColorBrush(Color.FromRgb(255, 32, 32)); 21 | red.Freeze(); 22 | green = new SolidColorBrush(Color.FromRgb(64, 200, 32)); 23 | green.Freeze(); 24 | } 25 | 26 | #region MapNumber変更通知プロパティ 27 | private string _MapNumber; 28 | 29 | public string MapNumber 30 | { 31 | get 32 | { return this._MapNumber; } 33 | set 34 | { 35 | if (this._MapNumber == value) 36 | return; 37 | this._MapNumber = value; 38 | this.RaisePropertyChanged(); 39 | } 40 | } 41 | #endregion 42 | 43 | 44 | #region Name変更通知プロパティ 45 | private string _Name; 46 | 47 | public string Name 48 | { 49 | get 50 | { return this._Name; } 51 | set 52 | { 53 | if (this._Name == value) 54 | return; 55 | this._Name = value; 56 | this.RaisePropertyChanged(); 57 | } 58 | } 59 | #endregion 60 | 61 | 62 | #region AreaName変更通知プロパティ 63 | private string _AreaName; 64 | 65 | public string AreaName 66 | { 67 | get 68 | { return this._AreaName; } 69 | set 70 | { 71 | if (this._AreaName == value) 72 | return; 73 | this._AreaName = value; 74 | this.RaisePropertyChanged(); 75 | } 76 | } 77 | #endregion 78 | 79 | 80 | #region Current変更通知プロパティ 81 | private string _Current; 82 | 83 | public string Current 84 | { 85 | get 86 | { return this._Current; } 87 | set 88 | { 89 | if (this._Current == value) 90 | return; 91 | this._Current = value; 92 | this.RaisePropertyChanged(); 93 | } 94 | } 95 | #endregion 96 | 97 | 98 | #region Max変更通知プロパティ 99 | private string _Max; 100 | 101 | public string Max 102 | { 103 | get 104 | { return this._Max; } 105 | set 106 | { 107 | if (this._Max == value) 108 | return; 109 | this._Max = value; 110 | this.RaisePropertyChanged(); 111 | } 112 | } 113 | #endregion 114 | 115 | 116 | #region SelectedRank変更通知プロパティ 117 | private string _SelectedRank; 118 | 119 | public string SelectedRank 120 | { 121 | get 122 | { return this._SelectedRank; } 123 | set 124 | { 125 | if (this._SelectedRank == value) 126 | return; 127 | this._SelectedRank = value; 128 | this.RaisePropertyChanged(); 129 | } 130 | } 131 | #endregion 132 | 133 | public Visibility SelectedRankVisibility 134 | => string.IsNullOrEmpty(this.SelectedRank) ? Visibility.Collapsed : Visibility.Visible; 135 | 136 | #region RemainingCountMin 変更通知プロパティ 137 | private string _RemainingCountMin; 138 | 139 | public string RemainingCountMin 140 | { 141 | get 142 | { return this._RemainingCountMin; } 143 | set 144 | { 145 | if (this._RemainingCountMin == value) 146 | return; 147 | this._RemainingCountMin = value; 148 | this.RaisePropertyChanged(); 149 | this.RaisePropertyChanged(nameof(this.IsSingleRemainingCount)); 150 | } 151 | } 152 | #endregion 153 | 154 | #region RemainingCountMax 変更通知プロパティ 155 | private string _RemainingCountMax; 156 | 157 | public string RemainingCountMax 158 | { 159 | get 160 | { return this._RemainingCountMax; } 161 | set 162 | { 163 | if (this._RemainingCountMax == value) 164 | return; 165 | this._RemainingCountMax = value; 166 | this.RaisePropertyChanged(); 167 | this.RaisePropertyChanged(nameof(this.IsSingleRemainingCount)); 168 | } 169 | } 170 | #endregion 171 | 172 | public bool IsSingleRemainingCount 173 | => this.RemainingCountMin == this.RemainingCountMax; 174 | 175 | 176 | #region RemainingCountTransportS変更通知プロパティ 177 | private string _RemainingCountTransportS; 178 | 179 | public string RemainingCountTransportS 180 | { 181 | get 182 | { return this._RemainingCountTransportS; } 183 | set 184 | { 185 | if (this._RemainingCountTransportS == value) 186 | return; 187 | this._RemainingCountTransportS = value; 188 | this.RaisePropertyChanged(); 189 | } 190 | } 191 | #endregion 192 | 193 | 194 | #region IsCleared変更通知プロパティ 195 | private bool _IsCleared; 196 | 197 | public bool IsCleared 198 | { 199 | get 200 | { return this._IsCleared; } 201 | set 202 | { 203 | if (this._IsCleared == value) 204 | return; 205 | this._IsCleared = value; 206 | this.RaisePropertyChanged(); 207 | } 208 | } 209 | #endregion 210 | 211 | 212 | #region GaugeColor変更通知プロパティ 213 | private SolidColorBrush _GaugeColor; 214 | 215 | public SolidColorBrush GaugeColor 216 | { 217 | get 218 | { return this._GaugeColor; } 219 | set 220 | { 221 | if (Equals(this._GaugeColor, value)) 222 | return; 223 | this._GaugeColor = value; 224 | this.RaisePropertyChanged(); 225 | } 226 | } 227 | #endregion 228 | 229 | 230 | #region IsRankSelected変更通知プロパティ 231 | private bool _IsRankSelected; 232 | 233 | public bool IsRankSelected 234 | { 235 | get 236 | { return this._IsRankSelected; } 237 | set 238 | { 239 | if (this._IsRankSelected == value) 240 | return; 241 | this._IsRankSelected = value; 242 | this.RaisePropertyChanged(); 243 | } 244 | } 245 | #endregion 246 | 247 | 248 | #region IsLoading変更通知プロパティ 249 | private bool _IsLoading; 250 | 251 | public bool IsLoading 252 | { 253 | get 254 | { return this._IsLoading; } 255 | set 256 | { 257 | if (this._IsLoading == value) 258 | return; 259 | this._IsLoading = value; 260 | this.RaisePropertyChanged(); 261 | this.RaiseVisibilityChanged(); 262 | } 263 | } 264 | #endregion 265 | 266 | 267 | #region IsSupported変更通知プロパティ 268 | private bool _IsSupported; 269 | 270 | public bool IsSupported 271 | { 272 | get 273 | { return this._IsSupported; } 274 | set 275 | { 276 | if (this._IsSupported == value) 277 | return; 278 | this._IsSupported = value; 279 | this.RaisePropertyChanged(); 280 | this.RaiseVisibilityChanged(); 281 | } 282 | } 283 | #endregion 284 | 285 | public Visibility IsUnSupportedVisibility 286 | => !this.IsLoading && !this.IsSupported ? Visibility.Visible : Visibility.Collapsed; 287 | 288 | #region IsInfinity変更通知プロパティ 289 | private bool _IsInfinity; 290 | 291 | public bool IsInfinity 292 | { 293 | get 294 | { return this._IsInfinity; } 295 | set 296 | { 297 | if (this._IsInfinity == value) 298 | return; 299 | this._IsInfinity = value; 300 | this.RaisePropertyChanged(); 301 | this.RaiseVisibilityChanged(); 302 | } 303 | } 304 | #endregion 305 | 306 | public Visibility IsInfinityVisibility 307 | => !this.IsLoading && this.IsInfinity ? Visibility.Visible : Visibility.Collapsed; 308 | 309 | public Visibility IsCountVisibility 310 | => !this.IsLoading && this.IsSupported && !this.IsInfinity ? Visibility.Visible : Visibility.Collapsed; 311 | 312 | #region GaugeType変更通知プロパティ 313 | private GaugeType _GaugeType; 314 | 315 | public GaugeType GaugeType 316 | { 317 | get 318 | { return this._GaugeType; } 319 | set 320 | { 321 | if (this._GaugeType == value) 322 | return; 323 | this._GaugeType = value; 324 | this.RaisePropertyChanged(); 325 | } 326 | } 327 | #endregion 328 | 329 | private MapData _source; 330 | 331 | public MapViewModel(MapData info) 332 | { 333 | this._source = info; 334 | this.MapNumber = info.MapNumber; 335 | this.Name = info.Name; 336 | this.AreaName = info.AreaName; 337 | this.Current = info.Current?.ToString() ?? "???"; 338 | this.Max = info.Max?.ToString() ?? "???"; 339 | this.SelectedRank = info.Eventmap?.SelectedRank.ToString(); 340 | this.IsCleared = info.IsCleared == 1; 341 | this.IsRankSelected = info.Eventmap == null 342 | || info.Eventmap.SelectedRank != 0 343 | || info.Eventmap.NowMapHp != 9999; 344 | this.GaugeType = info.GaugeType; 345 | 346 | this.GaugeColor = green; 347 | this.IsSupported = true; 348 | this.IsInfinity = false; 349 | this.IsLoading = true; 350 | 351 | this.UpdateRemainingCount(); 352 | } 353 | 354 | 355 | public void UpdateRemainingCount() 356 | { 357 | try 358 | { 359 | this._source.GetRemainingCount() 360 | .ContinueWith(t => this.Update(t.Result)); 361 | } 362 | catch (AggregateException e) 363 | { 364 | Debug.WriteLine(e); 365 | } 366 | } 367 | 368 | private void Update(RemainingCount remainingCount) 369 | { 370 | Application.Current.Dispatcher.Invoke(() => 371 | { 372 | this.IsLoading = false; 373 | this.IsSupported = remainingCount != null; 374 | if (!this.IsSupported) 375 | { 376 | this.GaugeColor = red; 377 | return; 378 | } 379 | 380 | this.RemainingCountMin = remainingCount.Min.ToString(); 381 | this.RemainingCountMax = remainingCount.Max.ToString(); 382 | this.RemainingCountTransportS = this._source.GetRemainingCountTransportS().ToString(); 383 | this.IsInfinity = remainingCount == RemainingCount.MaxValue; 384 | this.GaugeColor = remainingCount.Min < 2 ? red : green; 385 | }); 386 | } 387 | 388 | private void RaiseVisibilityChanged() 389 | { 390 | this.RaisePropertyChanged(nameof(this.IsCountVisibility)); 391 | this.RaisePropertyChanged(nameof(this.IsUnSupportedVisibility)); 392 | this.RaisePropertyChanged(nameof(this.IsInfinityVisibility)); 393 | } 394 | } 395 | } 396 | -------------------------------------------------------------------------------- /EventMapHpViewer/Views/Settings/BossSettings.xaml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 61 | 62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 73 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 90 | 91 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 105 | 106 | 111 | 112 | 116 | 129 | 130 | 131 | 132 | 134 | 136 | 138 | 140 | 142 | 143 | 144 | 145 | 146 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 166 | 174 | 175 | 178 | 186 | 187 | 190 | 194 | 196 | 197 | 200 | 201 | 202 | 203 | 204 | 207 | 211 | 213 | 214 | 217 | 218 | 219 | 220 | 221 | 224 | 229 | 230 | 233 | 234 | 235 | 236 | 237 | 238 | 246 | 254 | 262 | 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /EventMapHpViewer/EventMapHpViewer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {912029C5-C147-459B-A735-3D559B2F193D} 8 | Library 9 | Properties 10 | EventMapHpViewer 11 | EventMapHpViewer 12 | v4.6 13 | 512 14 | ..\ 15 | true 16 | 12.0.51020.0 17 | 18 | 19 | 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | latest 28 | 29 | 30 | none 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | false 37 | latest 38 | 39 | 40 | 41 | ..\packages\KanColleViewer.Composition.1.4.0\lib\net45\KanColleViewer.Composition.dll 42 | False 43 | 44 | 45 | ..\packages\KanColleViewer.Controls.1.3.2\lib\net46\KanColleViewer.Controls.dll 46 | False 47 | 48 | 49 | ..\packages\KanColleViewer.PluginAnalyzer.1.1.1.0\lib\net46\KanColleViewer.PluginAnalyzer.dll 50 | False 51 | 52 | 53 | ..\packages\KanColleWrapper.1.6.2\lib\net46\KanColleWrapper.dll 54 | False 55 | 56 | 57 | ..\packages\LivetCask.1.3.1.0\lib\net45\Livet.dll 58 | False 59 | 60 | 61 | ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll 62 | False 63 | 64 | 65 | ..\packages\MetroRadiance.2.4.0\lib\net46\MetroRadiance.dll 66 | False 67 | 68 | 69 | ..\packages\MetroRadiance.Chrome.2.2.0\lib\net46\MetroRadiance.Chrome.dll 70 | False 71 | 72 | 73 | ..\packages\MetroRadiance.Core.2.4.0\lib\net46\MetroRadiance.Core.dll 74 | False 75 | 76 | 77 | ..\packages\MetroTrilithon.0.2.0\lib\portable-net45+win+wp80+MonoAndroid10+xamarinios10+MonoTouch10\MetroTrilithon.dll 78 | False 79 | 80 | 81 | ..\packages\MetroTrilithon.Desktop.0.2.3\lib\net46\MetroTrilithon.Desktop.dll 82 | False 83 | 84 | 85 | False 86 | 87 | 88 | ..\packages\Nekoxy.1.5.3.21\lib\net45\Nekoxy.dll 89 | False 90 | 91 | 92 | 93 | 94 | ..\packages\StatefulModel.0.6.0\lib\portable-net45+win+wp80+MonoAndroid10+xamarinios10+MonoTouch10\StatefulModel.dll 95 | False 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll 104 | False 105 | 106 | 107 | ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll 108 | False 109 | 110 | 111 | ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll 112 | False 113 | 114 | 115 | ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll 116 | False 117 | 118 | 119 | 120 | 121 | False 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | ..\packages\Nekoxy.1.5.3.21\lib\net45\TrotiNet.dll 131 | False 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | SettingsView.xaml 172 | 173 | 174 | BossSettings.xaml 175 | 176 | 177 | TpSettings.xaml 178 | 179 | 180 | TpSettingsListView.xaml 181 | 182 | 183 | ToolView.xaml 184 | 185 | 186 | 187 | 188 | 189 | 190 | MSBuild:Compile 191 | Designer 192 | 193 | 194 | Designer 195 | MSBuild:Compile 196 | 197 | 198 | Designer 199 | MSBuild:Compile 200 | 201 | 202 | Designer 203 | MSBuild:Compile 204 | 205 | 206 | Designer 207 | MSBuild:Compile 208 | 209 | 210 | Designer 211 | MSBuild:Compile 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | このプロジェクトは、このコンピューターにはない NuGet パッケージを参照しています。これらをダウンロードするには、NuGet パッケージの復元を有効にしてください。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。不足しているファイルは {0} です。 231 | 232 | 233 | 234 | 235 | mkdir "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)\Plugins" 236 | xcopy /Y "$(TargetDir)*.*" "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)" 237 | move "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)\$(TargetName).*" "$(SolutionDir)Grabacr07.KanColleViewer\bin\$(ConfigurationName)\Plugins" 238 | 239 | 246 | --------------------------------------------------------------------------------