diff --git a/EventMapHpViewer/EventMapHpViewer.csproj b/EventMapHpViewer/EventMapHpViewer.csproj
index 12d4c35..a8bffc9 100644
--- a/EventMapHpViewer/EventMapHpViewer.csproj
+++ b/EventMapHpViewer/EventMapHpViewer.csproj
@@ -34,6 +34,7 @@
prompt
4
false
+ latest
diff --git a/EventMapHpViewer/Models/MapData.cs b/EventMapHpViewer/Models/MapData.cs
index 8b5f6e2..9af3cfa 100644
--- a/EventMapHpViewer/Models/MapData.cs
+++ b/EventMapHpViewer/Models/MapData.cs
@@ -13,6 +13,7 @@ namespace EventMapHpViewer.Models
{
public class MapData
{
+ private readonly RemoteSettingsClient client = new RemoteSettingsClient();
public int Id { get; set; }
public int IsCleared { get; set; }
public int IsExBoss { get; set; }
@@ -76,31 +77,30 @@ public async Task GetRemainingCount()
if (MapHpSettings.UseLocalBossSettings)
{
var settings = BossSettingsWrapper.FromSettings.List
- .Where(x => x.Id == this.Id)
+ .Where(x => x.MapId == this.Id)
.Where(x => x.Rank == (int)this.Eventmap.SelectedRank)
- .Where(x => x.GaugeNum == (this.Eventmap.GaugeNum ?? 1))
+ .Where(x => x.GaugeNum == this.Eventmap.GaugeNum)
.ToArray();
if (settings.Any())
return this.CalculateRemainingCount(settings);
}
else
{
- var client = new RemoteSettingsClient();
var remoteBossData = await client.GetSettings(
RemoteSettingsClient.BuildBossSettingsUrl(
MapHpSettings.RemoteBossSettingsUrl,
this.Id,
(int)this.Eventmap.SelectedRank,
- this.Eventmap.GaugeNum ?? 1));
+ this.Eventmap.GaugeNum ?? 1)); // GaugeNum がない場合どうしよう?とりあえず1
client.CloseConnection();
if (remoteBossData == null)
return null;
- if (!remoteBossData.Any(x => x.isLast))
+ if (!remoteBossData.Any(x => x.last))
return null;
- if(!remoteBossData.Any(x => !x.isLast))
+ if(!remoteBossData.Any(x => !x.last))
return null;
return this.CalculateRemainingCount(BossSettingsWrapper.Parse(remoteBossData)); //イベント海域(リモートデータ)
diff --git a/EventMapHpViewer/Models/Raw/map_exboss.cs b/EventMapHpViewer/Models/Raw/map_exboss.cs
index bf30f2a..51cdf79 100644
--- a/EventMapHpViewer/Models/Raw/map_exboss.cs
+++ b/EventMapHpViewer/Models/Raw/map_exboss.cs
@@ -8,23 +8,10 @@ namespace EventMapHpViewer.Models.Raw
{
class map_exboss
{
- public bool isLast { get; set; }
- public Ship ship { get; set; }
-
- public class Ship
- {
- //public string shipName { get; set; }
- //public int shipId { get; set; }
- //public int shipLv { get; set; }
- public int maxhp { get; set; }
- //public Slot[] slot { get; set; }
- //public int[] param { get; set; }
- }
-
- //public class Slot
- //{
- // public int slotitemId { get; set; }
- // public string slotitemName { get; set; }
- //}
+ public int mapid { get; set; }
+ public int rank { get; set; }
+ public int? gauge { get; set; }
+ public int maxhp { get; set; }
+ public bool last { get; set; }
}
}
diff --git a/EventMapHpViewer/Models/Settings/AutoCalcTpSettings.cs b/EventMapHpViewer/Models/Settings/AutoCalcTpSettings.cs
index f4b4db5..507c4b8 100644
--- a/EventMapHpViewer/Models/Settings/AutoCalcTpSettings.cs
+++ b/EventMapHpViewer/Models/Settings/AutoCalcTpSettings.cs
@@ -76,9 +76,14 @@ public AutoCalcTpSettings()
private AutoCalcTpSettings(string stypeTp, string slotitemTp, string shipTp)
{
- this.ShipTypeTp = !string.IsNullOrEmpty(stypeTp) ? DynamicJson.Parse(stypeTp) : Default.ShipTypeTp;
- this.SlotItemTp = !string.IsNullOrEmpty(slotitemTp) ? DynamicJson.Parse(slotitemTp) : Default.SlotItemTp;
- this.ShipTp = !string.IsNullOrEmpty(shipTp) ? DynamicJson.Parse(shipTp) : Default.ShipTp;
+ try { this.ShipTypeTp = DynamicJson.Parse(stypeTp); }
+ catch { this.ShipTypeTp = Default.ShipTypeTp; }
+
+ try { this.SlotItemTp = DynamicJson.Parse(slotitemTp); }
+ catch { this.SlotItemTp = Default.SlotItemTp; }
+
+ try { this.ShipTp = DynamicJson.Parse(shipTp); }
+ catch { this.ShipTp = Default.ShipTp; }
}
private AutoCalcTpSettings(IEnumerable stypeTp, IEnumerable slotitemTp, IEnumerable shipTp)
diff --git a/EventMapHpViewer/Models/Settings/BossSettingsWrapper.cs b/EventMapHpViewer/Models/Settings/BossSettingsWrapper.cs
index 68f4471..1de5394 100644
--- a/EventMapHpViewer/Models/Settings/BossSettingsWrapper.cs
+++ b/EventMapHpViewer/Models/Settings/BossSettingsWrapper.cs
@@ -27,17 +27,26 @@ private set
public BossSettingsWrapper(string json = "")
{
- this.List = !string.IsNullOrEmpty(json)
- ? DynamicJson.Parse(json)
- : new ObservableSynchronizedCollection();
+ try
+ {
+ BossSettingForParse[] parsed = DynamicJson.Parse(json);
+ this.List = new ObservableSynchronizedCollection(parsed.Select(x => x.ToValue()));
+ }
+ catch
+ {
+ this.List = new ObservableSynchronizedCollection();
+ }
}
public static IEnumerable Parse(IEnumerable source)
{
return source.Select(x => new BossSetting
{
- BossHP = x.ship.maxhp,
- IsLast = x.isLast,
+ MapId = x.mapid,
+ Rank = x.rank,
+ GaugeNum = x.gauge,
+ BossHP = x.maxhp,
+ IsLast = x.last,
});
}
@@ -49,13 +58,31 @@ public static BossSettingsWrapper FromSettings
public class BossSetting
{
- public int Id { get; set; }
+ public int MapId { get; set; }
public int Rank { get; set; }
- public int GaugeNum { get; set; }
+ public int? GaugeNum { get; set; }
public int BossHP { get; set; }
public bool IsLast { get; set; }
}
+ public class BossSettingForParse
+ {
+ public int MapId { get; set; }
+ public int Rank { get; set; }
+ public string GaugeNum { get; set; } // DynamicJson は int? に Parse できない
+ public int BossHP { get; set; }
+ public bool IsLast { get; set; }
+ public BossSetting ToValue()
+ => new BossSetting
+ {
+ MapId = this.MapId,
+ Rank = this.Rank,
+ GaugeNum = int.TryParse(this.GaugeNum, out var num) ? num : (int?)null,
+ BossHP = this.BossHP,
+ IsLast = this.IsLast,
+ };
+ }
+
static class BossSettingsWrapperExtensions
{
public static void Save(this BossSettingsWrapper settings)
diff --git a/EventMapHpViewer/Models/Settings/MapHpSettings.cs b/EventMapHpViewer/Models/Settings/MapHpSettings.cs
index 5f5ce53..6e7f6a4 100644
--- a/EventMapHpViewer/Models/Settings/MapHpSettings.cs
+++ b/EventMapHpViewer/Models/Settings/MapHpSettings.cs
@@ -57,7 +57,7 @@ static class MapHpSettings
public static SerializableProperty RemoteBossSettingsUrl { get; }
= new SerializableProperty(GetKey(), roamingProvider,
- "https://kctadil-admin.azurewebsites.net/admin/maphp/{version}/{id}/{rank}/{gaugeNum}"
+ "https://kctadilstorage.blob.core.windows.net/viewer/maphp/{mapId}/{rank}/{gaugeNum}.json"
) { AutoSave = true };
#endregion
diff --git a/EventMapHpViewer/Models/Settings/RemoteSettingsClient.cs b/EventMapHpViewer/Models/Settings/RemoteSettingsClient.cs
index 35cc807..858b0b2 100644
--- a/EventMapHpViewer/Models/Settings/RemoteSettingsClient.cs
+++ b/EventMapHpViewer/Models/Settings/RemoteSettingsClient.cs
@@ -10,6 +10,7 @@
using System.Net.Http;
using System.Reflection;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@@ -19,14 +20,18 @@ class RemoteSettingsClient
{
private HttpClient client;
- private ConcurrentDictionary lastModified;
+ private readonly ConcurrentDictionary lastModified;
- private ConcurrentDictionary caches;
+ private readonly ConcurrentDictionary caches;
private TimeSpan cacheTtl;
private bool updating;
+ private static readonly object errorObject = new object();
+
+ public bool IsCacheError { get; set; } = true;
+
#if DEBUG
public RemoteSettingsClient() : this(TimeSpan.FromSeconds(10)) { }
#else
@@ -62,11 +67,12 @@ public async Task GetSettings(string url)
if (DateTimeOffset.Now - lm < this.cacheTtl)
{
- object value;
- if (this.caches.TryGetValue(url, out value)
- && value is T)
+ if (this.caches.TryGetValue(url, out var value))
{
- return (T)value;
+ if (value is T)
+ return (T)value;
+ else if (value == errorObject)
+ return null;
}
}
this.updating = true;
@@ -85,6 +91,7 @@ public async Task GetSettings(string url)
if (!response.IsSuccessStatusCode)
{
// 200 じゃなかった
+ this.CacheError(url, lm);
return null;
}
@@ -97,6 +104,13 @@ public async Task GetSettings(string url)
catch (HttpRequestException)
{
// HTTP リクエストに失敗した
+ this.CacheError(url, lm);
+ return null;
+ }
+ catch
+ {
+ // 不正な JSON 等
+ this.CacheError(url, lm);
return null;
}
finally
@@ -105,6 +119,14 @@ public async Task GetSettings(string url)
}
}
+ private void CacheError(string url, DateTimeOffset lastModified)
+ {
+ if (!this.IsCacheError)
+ return;
+ this.lastModified.TryUpdate(url, DateTimeOffset.Now, lastModified);
+ this.caches.AddOrUpdate(url, errorObject, (_, __) => errorObject);
+ }
+
public void CloseConnection()
{
this.client?.Dispose();
@@ -152,7 +174,7 @@ public static string BuildBossSettingsUrl(string url, int id, int rank, int gaug
return BuildUrl(url, new Dictionary
{
{ "version", $"{MapHpViewer.version}" },
- { "id", id.ToString() },
+ { "mapId", id.ToString() },
{ "rank", rank.ToString() },
{ "gaugeNum", gaugeNum.ToString() },
});
@@ -164,7 +186,8 @@ public static string BuildUrl(string url, IDictionary placeHolde
return url;
foreach(var placeHolder in placeHolders)
{
- url = url.Replace($"{{{placeHolder.Key}}}", placeHolder.Value);
+ var regex = new Regex($"{{{placeHolder.Key}}}", RegexOptions.IgnoreCase | RegexOptions.Singleline);
+ url = regex.Replace(url, placeHolder.Value);
}
return url;
}
diff --git a/EventMapHpViewer/ViewModels/Settings/BossSettingsViewModel.cs b/EventMapHpViewer/ViewModels/Settings/BossSettingsViewModel.cs
index 097bf33..73dbdd3 100644
--- a/EventMapHpViewer/ViewModels/Settings/BossSettingsViewModel.cs
+++ b/EventMapHpViewer/ViewModels/Settings/BossSettingsViewModel.cs
@@ -44,16 +44,16 @@ public bool UseLocalBossSettings
}
#endregion
- #region Id
- private int _Id;
- public int Id
+ #region MapId
+ private int _MapId;
+ public int MapId
{
- get => this._Id;
+ get => this._MapId;
set
{
- if (value == this._Id)
+ if (value == this._MapId)
return;
- this._Id = value;
+ this._MapId = value;
this.RaisePropertyChanged();
}
}
@@ -100,8 +100,8 @@ public int Rank
#endregion
#region GaugeNum
- private int _GaugeNum;
- public int GaugeNum
+ private string _GaugeNum;
+ public string GaugeNum
{
get => this._GaugeNum;
set
@@ -148,15 +148,15 @@ public bool IsLast
public bool IsAddEnabled
{
get => !this.Settings.List.Any(
- x => x.Id == this.Id
+ x => x.MapId == this.MapId
&& x.Rank == this.Rank
- && x.GaugeNum == this.GaugeNum
+ && x.GaugeNum.ToString() == this.GaugeNum
&& x.BossHP == this.BossHP
&& x.IsLast == this.IsLast
)
- && this.Id != default
+ && this.MapId != default
&& this.Rank != default
- && this.GaugeNum != default
+ // && this.GaugeNum != default // 空もありとする
&& this.BossHP != default;
}
#endregion
@@ -178,15 +178,15 @@ public BossSetting SelectedBossSetting
this._SelectedBossSetting = value;
if(value != null)
{
- this.Id = value.Id;
+ this.MapId = value.MapId;
this.Rank = value.Rank;
- this.GaugeNum = value.GaugeNum;
+ this.GaugeNum = value.GaugeNum.ToString();
this.BossHP = value.BossHP;
this.IsLast = value.IsLast;
}
else
{
- this.Id = default;
+ this.MapId = default;
this.Rank = default;
this.GaugeNum = default;
this.BossHP = default;
@@ -234,7 +234,7 @@ public BossSettingsViewModel()
this.Settings = BossSettingsWrapper.FromSettings;
this.BossSettings = this.Settings.List
- .ToSyncedSortedObservableCollection(x => $"{x.Id:D4}{x.Rank:D2}{x.GaugeNum:D2}{(x.IsLast ? 1 : 0)}{x.BossHP:D4}")
+ .ToSyncedSortedObservableCollection(x => $"{x.MapId:D4}{x.Rank:D2}{x.GaugeNum ?? 0:D2}{(x.IsLast ? 1 : 0)}{x.BossHP:D4}")
.ToSyncedSynchronizationContextCollection(SynchronizationContext.Current)
.ToSyncedReadOnlyNotifyChangedCollection();
}
@@ -243,9 +243,9 @@ public void Add()
{
var newValue = new BossSetting
{
- Id = this.Id,
+ MapId = this.MapId,
Rank = this.Rank,
- GaugeNum = this.GaugeNum,
+ GaugeNum = int.TryParse(this.GaugeNum, out var num) ? num : (int?)null,
BossHP = this.BossHP,
IsLast = this.IsLast
};
diff --git a/EventMapHpViewer/ViewModels/ToolViewModel.cs b/EventMapHpViewer/ViewModels/ToolViewModel.cs
index f153a67..4e80790 100644
--- a/EventMapHpViewer/ViewModels/ToolViewModel.cs
+++ b/EventMapHpViewer/ViewModels/ToolViewModel.cs
@@ -58,7 +58,6 @@ public ToolViewModel(MapInfoProxy proxy)
public void Initialize()
{
- Debug.WriteLine("ToolViewModel: Initialize()");
KanColleClient.Current.Homeport.Organization
.Subscribe(nameof(Organization.Fleets), this.UpdateFleets, false)
.Subscribe(nameof(Organization.Combined), this.UpdateTransportCapacity, false)
diff --git a/EventMapHpViewer/Views/Settings/BossSettings.xaml b/EventMapHpViewer/Views/Settings/BossSettings.xaml
index 17db2ba..83cac73 100644
--- a/EventMapHpViewer/Views/Settings/BossSettings.xaml
+++ b/EventMapHpViewer/Views/Settings/BossSettings.xaml
@@ -90,8 +90,7 @@
-
-
+
@@ -130,8 +129,8 @@
-
+
+ Margin="0,4"
+ Prompt="">
+ AllowsEmpty="True"/>
@@ -204,7 +206,8 @@
Text="ボスHP: "/>
+ Margin="0,4"
+ Prompt="">