42 Commits

Author SHA1 Message Date
4758b65159 build: Update project version 2025-06-17 01:16:22 +08:00
de3196d38a fix: Revise the tag of a log point 2025-06-17 01:16:11 +08:00
c2311fb7a4 feat: Add new event sources 2025-06-17 01:15:25 +08:00
7562be2c09 ci: Update plugins 2025-06-17 01:12:55 +08:00
a8f46113d4 build: Update project version 2025-06-06 19:33:15 +08:00
99736f114d style: Code cleanup 2025-06-06 19:32:42 +08:00
4d1a008106 feat: Add logs 2025-06-06 19:32:31 +08:00
9318cbca4e feat: Add new event sources 2025-06-06 19:31:27 +08:00
a162f345c4 ci: Update plugins 2025-06-06 19:30:21 +08:00
1af4afc7c6 build: Update project version 2025-05-07 22:56:45 +08:00
a3efe939e8 fix: Fix TTS COM exception in IL2CPP 2025-05-07 22:56:32 +08:00
5daee1a01a feat: Add TTS related settings 2025-05-06 20:35:52 +08:00
2d5d305528 feat: Implement TTS 2025-05-06 20:35:08 +08:00
8da46c0511 build: Update project version 2025-04-29 19:54:46 +08:00
75b5d7708c fix: Disable force HTTPS in NOAA Atom worker when debugging 2025-04-29 19:54:27 +08:00
5b2177a795 feat: Add using raw location name settings for CENC earthquake reports 2025-04-29 19:54:16 +08:00
8cb33dca5f ci: Update plugins 2025-04-29 19:53:24 +08:00
ae2e0af18a fix: Improve ongoing report round-robin period 2025-04-29 19:52:41 +08:00
2ac5a3d4f0 build: Update project version 2025-04-08 10:01:06 +08:00
5f78a1afde refactor: Code cleanup 2025-04-08 10:00:47 +08:00
ef5cf78a03 feat: Add display culture config 2025-04-08 10:00:28 +08:00
b60e62af70 feat: Adapt to breaking changes 2025-04-08 10:00:01 +08:00
3e59fe1462 feat: Implement region editor 2025-04-08 09:56:47 +08:00
4b4bf5ed65 ci: Update plugins 2025-04-08 09:53:33 +08:00
a4f78b3a95 build: Update project version 2025-03-24 00:07:35 +08:00
074a58dabd perf: Optimize performance for status view 2025-03-24 00:06:51 +08:00
a2ef175a81 fix: Fix potentially bad formats in culture info 2025-03-24 00:06:29 +08:00
915ba55c2e fix: Correct lifecycle of event listeners 2025-03-24 00:05:35 +08:00
f154a2a468 fix: Fix history list view flashing hard on update 2025-03-24 00:04:29 +08:00
c52d438d40 ci: Update plugins 2025-03-24 00:03:33 +08:00
8d3f53ba13 perf: Improve performance for line renderer 2025-03-20 21:49:28 +08:00
1db25e62e7 fix: Fix wave circle shape when hypocenter is near antimeridian 2025-03-20 21:47:52 +08:00
18312176d9 refactor: Decouple grouping logic from core worker 2025-03-20 17:53:10 +08:00
5be6e32b03 refactor: Pull up map tile cache manager 2025-03-20 17:52:17 +08:00
b33e5ca223 build: Update project version 2025-02-26 15:58:15 +08:00
fe4430b1bf feat: Add new event sources 2025-02-26 15:58:02 +08:00
5a48073152 ci: Update plugins 2025-02-26 15:57:04 +08:00
41c1e6f9fd fix: Fix network events invalidating map view 2025-02-26 15:36:02 +08:00
0743fa45eb fix: Keep ongoing events if present on reported 2025-02-26 15:18:37 +08:00
7f2c0d2e23 fix: Keep ongoing events if present on reported 2025-02-26 15:05:34 +08:00
14202714cc fix: Fix error on polygon elements with holes 2025-02-26 01:20:18 +08:00
ce0c23805a refactor: Remove useless suppressions 2025-02-22 15:39:38 +08:00
384 changed files with 10430 additions and 618 deletions

View File

@@ -56,7 +56,7 @@ namespace Cryville.Common.Unity.UI {
const float _placeholderLength = 100;
int _firstIndex, _lastIndex;
readonly Stack<GameObject> _pool = new();
void Update() {
void LateUpdate() {
int axis = (int)m_direction;
int sign = m_direction == 0 ? 1 : -1;
float padding = axis == 0 ? m_padding.left : m_padding.top;

View File

@@ -1,19 +1,60 @@
using Cryville.Common.Font;
using Cryville.Common.Logging;
using Cryville.Common.Unity.UI;
using Cryville.Culture;
using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using UnityEngine;
using Logger = Cryville.Common.Logging.Logger;
namespace Cryville.EEW.Unity {
class App {
public static string AppDataPath { get; private set; }
public static Logger MainLogger { get; private set; }
static FileStream _logFileStream;
static StreamLoggerListener _logWriter;
static bool _init;
public static void Init() {
if (_init) return;
_init = true;
AppDataPath = Application.persistentDataPath;
var logPath = Directory.CreateDirectory(Path.Combine(AppDataPath, "logs"));
_logFileStream = new FileStream(
Path.Combine(
logPath.FullName,
string.Format(
CultureInfo.InvariantCulture,
"{0}.log",
DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmssfff", CultureInfo.InvariantCulture)
)
),
FileMode.Create, FileAccess.Write, FileShare.Read
);
_logWriter = new StreamLoggerListener(_logFileStream) { AutoFlush = true };
MainLogger = new Logger();
var listener = new InstantLoggerListener();
listener.Log += MainLogger.Log;
MainLogger.AddListener(_logWriter);
Application.logMessageReceivedThreaded += OnInternalLog;
MainLogger.Log(1, "App", null, "App Version: {0}", Application.version);
MainLogger.Log(1, "App", null, "Unity Version: {0}", Application.unityVersion);
MainLogger.Log(1, "App", null, "Operating System: {0}, Unity = {1}, Family = {2}", Environment.OSVersion, SystemInfo.operatingSystem, SystemInfo.operatingSystemFamily);
MainLogger.Log(1, "App", null, "Platform: Build = {0}, Unity = {1}", PlatformConfig.Name, Application.platform);
MainLogger.Log(1, "App", null, "Culture: {0}, UI = {1}, Unity = {2}", SharedCultures.CurrentCulture, SharedCultures.CurrentUICulture, Application.systemLanguage);
MainLogger.Log(1, "App", null, "Device: Model = {0}, Type = {1}", SystemInfo.deviceModel, SystemInfo.deviceType);
MainLogger.Log(1, "App", null, "Graphics: Name = {0}, Type = {1}, Vendor = {2}, Version = {3}", SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceType, SystemInfo.graphicsDeviceVendor, SystemInfo.graphicsDeviceVersion);
MainLogger.Log(1, "App", null, "Processor: Count = {0}, Frequency = {1}MHz, Type = {2}", SystemInfo.processorCount, SystemInfo.processorFrequency, SystemInfo.processorType);
MainLogger.Log(1, "App", null, "Initializing font manager");
foreach (var res in Resources.LoadAll<TextAsset>("cldr/common/validity")) {
IdValidity.Load(LoadXmlDocument(res));
}
@@ -25,7 +66,10 @@ namespace Cryville.EEW.Unity {
};
TMPLocalizedText.DefaultShader = Resources.Load<Shader>(PlatformConfig.TextShader);
MainLogger.Log(1, "App", null, "Loading config");
SharedSettings.Instance.Init();
MainLogger.Log(1, "App", null, "Initialized");
}
static readonly Encoding _encoding = new UTF8Encoding(false, true);
@@ -40,5 +84,16 @@ namespace Cryville.EEW.Unity {
using var reader = XmlReader.Create(stream, _xmlSettings);
return XDocument.Load(reader);
}
static void OnInternalLog(string condition, string stackTrace, LogType type) {
var l = type switch {
LogType.Log => 1,
LogType.Assert => 2,
LogType.Warning => 3,
LogType.Error or LogType.Exception => 4,
_ => 1,
};
MainLogger.Log(l, "Internal", null, "{0}\n{1}", condition, stackTrace);
}
}
}

View File

@@ -1,3 +1,3 @@
using System.Reflection;
[assembly: AssemblyVersion("0.0.1")]
[assembly: AssemblyVersion("0.0.8")]

View File

@@ -1,5 +1,9 @@
using Cryville.EEW.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Cryville.EEW.Unity {
@@ -8,11 +12,18 @@ namespace Cryville.EEW.Unity {
float SeverityColorMappingLuminanceMultiplier,
bool UseContinuousColor,
string ColorScheme,
string LocationNamer,
string OverrideTimeZone,
bool DoDisplayTimeZone,
bool DoSwitchBackToHistory,
string NowcastWarningDelayTolerance,
string OverrideDisplayCulture,
IReadOnlyCollection<TTSCultureConfig> TTSCultures,
bool DoIgnoreLanguageVariant,
IReadOnlyCollection<EventSourceConfig> EventSources
) {
public static Config Default => new(
@@ -20,11 +31,18 @@ namespace Cryville.EEW.Unity {
1f,
false,
"Default",
"FERegionLong",
null,
true,
true,
"1:00:00",
"",
new List<TTSCultureConfig> { new(SharedCultures.CurrentUICulture) },
true,
new List<EventSourceConfig> {
new JMAAtomEventSourceConfig(Array.Empty<string>()),
new UpdateCheckerEventSourceConfig(),
@@ -34,23 +52,45 @@ namespace Cryville.EEW.Unity {
}
[JsonPolymorphic(TypeDiscriminatorPropertyName = "Type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType)]
[JsonDerivedType(typeof(BMKGOpenDataEventSourceConfig), "BMKGOpenData")]
[JsonDerivedType(typeof(CWAOpenDataEventSourceConfig), "CWAOpenData")]
[JsonDerivedType(typeof(EMSCRealTimeEventSourceConfig), "EMSCRealTime")]
[JsonDerivedType(typeof(GeoNetEventSourceConfig), "GeoNet")]
[JsonDerivedType(typeof(GlobalQuakeServerEventSourceConfig), "GlobalQuakeServer")]
[JsonDerivedType(typeof(GlobalQuakeServer15EventSourceConfig), "GlobalQuakeServer15")]
[JsonDerivedType(typeof(JMAAtomEventSourceConfig), "JMAAtom")]
[JsonDerivedType(typeof(NOAAEventSourceConfig), "NOAA")]
[JsonDerivedType(typeof(UpdateCheckerEventSourceConfig), "UpdateChecker")]
[JsonDerivedType(typeof(USGSEventSourceConfig), "USGSQuakeML")]
[JsonDerivedType(typeof(WolfxEventSourceConfig), "Wolfx")]
abstract record EventSourceConfig();
record BMKGOpenDataEventSourceConfig([property: JsonRequired] string[] Subtypes) : EventSourceConfig;
record CWAOpenDataEventSourceConfig([property: JsonRequired] string Subtype, [property: JsonRequired] string Token) : EventSourceConfig;
record EMSCRealTimeEventSourceConfig() : EventSourceConfig;
record GeoNetEventSourceConfig(int MinimumMMI = 3, bool DoGetFullHistory = false, bool DoGetStrongMotionInfo = true) : EventSourceConfig;
record GlobalQuakeServerEventSourceConfig([property: JsonRequired] string Host, int Port = 38000) : EventSourceConfig;
record GlobalQuakeServer15EventSourceConfig(string Host, int Port = 38000) : GlobalQuakeServerEventSourceConfig(Host, Port);
record JMAAtomEventSourceConfig(IReadOnlyCollection<string> Filter = null, bool IsFilterWhitelist = false) : EventSourceConfig;
record NOAAEventSourceConfig([property: JsonRequired] string Subtype) : EventSourceConfig;
record UpdateCheckerEventSourceConfig : EventSourceConfig;
record WolfxEventSourceConfig(IReadOnlyCollection<string> Filter = null, bool IsFilterWhitelist = false) : EventSourceConfig;
record USGSEventSourceConfig([property: JsonRequired] string Subtype, bool UseGeoJSONFeeds, string[] Products) : EventSourceConfig;
record WolfxEventSourceConfig(IReadOnlyCollection<string> Filter = null, bool IsFilterWhitelist = false, bool UseRawCENCLocationName = false) : EventSourceConfig;
[JsonSerializable(typeof(Config))]
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSourceGenerationOptions(Converters = new Type[] { typeof(CultureInfoConverter) }, WriteIndented = true)]
sealed partial class ConfigSerializationContext : JsonSerializerContext { }
sealed class CultureInfoConverter : JsonConverter<CultureInfo> {
public override CultureInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
Debug.Assert(typeToConvert == typeof(CultureInfo));
var value = reader.GetString();
if (value == null) return CultureInfo.InvariantCulture;
if (value == "") return SharedCultures.CurrentUICulture;
return SharedCultures.Get(value);
}
public override void Write(Utf8JsonWriter writer, CultureInfo value, JsonSerializerOptions options) {
writer.WriteStringValue(value.Name);
}
}
}

View File

@@ -3,6 +3,7 @@
"rootNamespace": "",
"references": [
"GUID:b92f9c7ac10b1c04e86fc48210f62ab1",
"GUID:1e0937e40dadba24a97b7342c4559580",
"GUID:e5b7e7f40a80a814ba706299d68f9213",
"GUID:da293eebbcb9a4947a212534c52d1a32"
],

View File

@@ -15,17 +15,26 @@ namespace Cryville.EEW.Unity.Map {
MapElementManager m_layerElementSub;
[SerializeField]
GameObject m_prefabTile;
[SerializeField]
GameObject m_prefabBitmapHolder;
[SerializeField]
int m_maxMapTileZoom = 10;
[SerializeField]
bool m_isEditor;
readonly MapTileCacheManager _tiles = new();
MapTileCacheManager _tiles;
float _elementLayerZ;
void Start() {
_camera = GetComponent<Camera>();
_tiles = m_isEditor ? new EditorMapTileCacheManager() : new MapTileCacheManager();
_tiles.ExtraCachedZoomLevel = 20;
_tiles.Parent = m_layerTile;
_tiles.PrefabTile = m_prefabTile;
_tiles.PrefabBitmapHolder = m_prefabBitmapHolder;
_tiles.CacheDir = Application.temporaryCachePath;
_camera.orthographicSize = 0.5f / MathF.Max(1, (float)_camera.pixelWidth / _camera.pixelHeight);
_elementLayerZ = m_layerElement.transform.position.z;
if (m_layerElement != null) _elementLayerZ = m_layerElement.transform.position.z;
_mapElementUpdated = true;
}
void OnDestroy() {
@@ -70,7 +79,7 @@ namespace Cryville.EEW.Unity.Map {
}
}
void ZoomToMapElement() {
var aabb = m_layerElement.AABB;
var aabb = m_layerElement != null ? m_layerElement.AABB : null;
if (aabb is not RectangleF b) return;
if (b.Width * _camera.pixelHeight < _camera.pixelWidth * b.Height)
Scale = b.Height;
@@ -93,14 +102,17 @@ namespace Cryville.EEW.Unity.Map {
transform.localPosition = new(nx, Math.Clamp(transform.position.y, h / 2 - 1, -h / 2), -20);
var bounds = new Bounds((Vector2)transform.position, new Vector2(w, h));
int zoom = Math.Clamp((int)Math.Log(vz / 256, 2) + 1, 0, 10);
int zoom = Math.Clamp((int)Math.Log(vz / 256, 2) + 1, 0, m_maxMapTileZoom);
int zoomScale = 1 << zoom;
_tiles.MoveTo(
new(Mathf.FloorToInt(bounds.min.x * zoomScale), Mathf.FloorToInt(-bounds.max.y * zoomScale), zoom),
new(Mathf.CeilToInt(bounds.max.x * zoomScale), Mathf.CeilToInt(-bounds.min.y * zoomScale), zoom)
);
if (m_layerElement != null) {
m_layerElement.Scale = h;
}
if (m_layerElementSub != null) {
m_layerElementSub.Scale = h;
if (nx - w / 2 < 0) {
@@ -117,3 +129,4 @@ namespace Cryville.EEW.Unity.Map {
}
}
}
}

View File

@@ -0,0 +1,15 @@
using Cryville.EEW.Core.Map;
using System.IO;
using UnityEngine;
namespace Cryville.EEW.Unity.Map {
sealed class EditorMapTileCacheManager : MapTileCacheManager {
protected override MapTileBitmapHolder CreateBitmapHolder(MapTileIndex index) => new(
index,
GameObject.Instantiate(PrefabBitmapHolder, Parent, false),
new($"https://tile.openstreetmap.org/{index.Z}/{index.NX}/{index.NY}.png")
);
protected override string GetCacheFilePath(MapTileIndex index) => Path.Combine(CacheDir, $"map_editor/{index.Z}/{index.NX}/{index.NY}");
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 478198b8ecc0082449fa3f68795174a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -98,24 +98,25 @@ namespace Cryville.EEW.Unity.Map.Element {
for (int d = 0; d < 360; d++) {
Quaternion q = Quaternion.AngleAxis(d, axis);
Vector3 p = q * rp;
Vector2 p2 = ToTilePos(p).ToVector2();
if (lp2 != null) {
float dx = p2.x - lp2.Value.x;
if (MathF.Abs(dx) >= 0.5) {
_vertexBuffer[d] = p2.x < 0.5 ? p2 + new Vector2(1, 0) : p2 - new Vector2(1, 0);
renderer.AddSegment(_vertexBuffer, segmentIndex, d - segmentIndex + 1);
segmentIndex = d;
AddVertex(renderer, ref lp2, ref segmentIndex, d, p);
}
}
_vertexBuffer[d] = p2;
lp2 = p2;
}
Vector2 rp2 = ToTilePos(rp).ToVector2();
_vertexBuffer[360] = rp2;
AddVertex(renderer, ref lp2, ref segmentIndex, 360, rp);
renderer.AddSegment(_vertexBuffer, segmentIndex, 361 - segmentIndex);
}
renderer.SetMaterial(isHistory ? m_historyMaterial : m_ongoingMaterial);
}
void AddVertex(MultiLineRenderer renderer, ref Vector2? lp2, ref int segmentIndex, int d, Vector3 p) {
Vector2 p2 = ToTilePos(p).ToVector2();
if (lp2 != null && MathF.Abs(p2.x - lp2.Value.x) >= 0.5) {
_vertexBuffer[d] = p2.x < 0.5 ? p2 + new Vector2(1, 0) : p2 - new Vector2(1, 0);
renderer.AddSegment(_vertexBuffer, segmentIndex, d - segmentIndex + 1);
segmentIndex = d;
}
_vertexBuffer[d] = p2;
lp2 = p2;
}
static PointF ToTilePos(Vector3 p) => MapTileUtils.WorldToTilePos(new(MathF.Atan2(p.z, p.x) / MathF.PI * 180f, MathF.Asin(p.y) / MathF.PI * 180f));
}
}

View File

@@ -150,12 +150,8 @@ namespace Cryville.EEW.Unity.Map {
_mesh.Clear();
if (_positions == null) return;
if (_positionCount <= 1) return;
float hw = m_width / 2;
int maxVertexCount = 4 * (_positionCount - 1);
var vbuf = ArrayPool<Vector3>.Shared.Rent(maxVertexCount);
var ubuf = ArrayPool<Vector2>.Shared.Rent(maxVertexCount);
var ibuf = ArrayPool<int>.Shared.Rent(3 * (2 + 4 * (_positionCount - 2)));
float hw = m_width / 2;
int i, vi = 0, ii = 0, li = 0, ri = 1;
float uvScale = 1 / (m_tilingScale * m_width);
Vector2 p0 = _positions[0], p1 = default;
@@ -163,6 +159,12 @@ namespace Cryville.EEW.Unity.Map {
if ((p1 = _positions[i]) != p0) break;
}
if (i >= _positionCount) return;
int maxVertexCount = 4 * (_positionCount - 1);
var vbuf = ArrayPool<Vector3>.Shared.Rent(maxVertexCount);
var ubuf = ArrayPool<Vector2>.Shared.Rent(maxVertexCount);
var ibuf = ArrayPool<int>.Shared.Rent(3 * (2 + 4 * (_positionCount - 2)));
Vector2 dp0 = NormalizeSmallVector(p1 - p0), np0 = GetNormal(dp0 * hw);
vbuf[vi] = p0 - np0; ubuf[vi++] = new(0, 0);
vbuf[vi] = p0 + np0; ubuf[vi++] = new(0, 1);

View File

@@ -1,10 +1,15 @@
using Cryville.EEW.BMKGOpenData.Map;
using Cryville.EEW.Core;
using Cryville.EEW.CWAOpenData.Map;
using Cryville.EEW.EMSC.Map;
using Cryville.EEW.GeoNet.Map;
using Cryville.EEW.GlobalQuake.Map;
using Cryville.EEW.JMAAtom.Map;
using Cryville.EEW.Map;
using Cryville.EEW.NOAA.Map;
using Cryville.EEW.QuakeML.Map;
using Cryville.EEW.Report;
using Cryville.EEW.USGS.Map;
using Cryville.EEW.Wolfx.Map;
using System.Collections.Generic;
using System.Drawing;
@@ -23,6 +28,7 @@ namespace Cryville.EEW.Unity.Map {
readonly List<int> _displayingOrder = new();
public int Count => _displayingReports.Count;
public int OngoingCount => _displayingReports.Count - (_selected != null ? 1 : 0);
[SerializeField] MapElementManager m_subManager;
@@ -123,17 +129,24 @@ namespace Cryville.EEW.Unity.Map {
}
readonly ContextedGeneratorManager<IMapGeneratorContext, MapElement> _gen = new(new IContextedGenerator<IMapGeneratorContext, MapElement>[] {
new BMKGEarthquakeMapGenerator(),
new CENCEarthquakeMapGenerator(),
new CENCEEWMapGenerator(),
new CWAEarthquakeMapGenerator(),
new CWAEEWMapGenerator(),
new CWATsunamiMapGenerator(),
new EMSCRealTimeEventMapGenerator(),
new FujianEEWMapGenerator(),
new GeoNetQuakeHistoryMapGenerator(),
new GeoNetQuakeMapGenerator(),
new GeoNetStrongMapGenerator(),
new GlobalQuakeMapViewGenerator(),
new JMAAtomMapGenerator(),
new JMAEEWMapGenerator(),
new NOAAMapGenerator(),
new QuakeMLEventMapGenerator(),
new SichuanEEWMapGenerator(),
new USGSContoursMapGenerator(),
});
public UnityMapElement Build(object e, out CultureInfo culture, out int order) {
culture = CultureInfo.InvariantCulture;

View File

@@ -1,44 +1,21 @@
using Cryville.EEW.Core.Map;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
namespace Cryville.EEW.Unity.Map {
[RequireComponent(typeof(SpriteRenderer))]
sealed class MapTile : MonoBehaviour {
static readonly SemaphoreSlim _semaphore = new(2);
static readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(10) };
[SerializeField] Transform _idView;
public MapTileIndex Index { get; set; }
public bool IsEmpty { get; private set; }
Action<MapTile> _callback;
SpriteRenderer _renderer;
UnityWebRequest _req;
DownloadHandlerTexture _texHandler;
Texture2D _tex;
Sprite _sprite;
void Awake() {
_renderer = GetComponent<SpriteRenderer>();
}
FileInfo _localFile;
bool _downloadDone;
public void Load(MapTileIndex index, string cacheDir, Action<MapTile> onUpdated) {
public void Init(MapTileIndex index) {
Index = index;
_callback = onUpdated;
_localFile = new(Path.Combine(cacheDir, $"map/{Index.Z}/{Index.NX}/{Index.NY}"));
float z = 1 << index.Z;
transform.localPosition = new(index.X / z, -(index.Y + 1) / z, -index.Z / 100f);
transform.localScale = new Vector3(1 / z, 1 / z, 1);
@@ -46,71 +23,22 @@ namespace Cryville.EEW.Unity.Map {
byte e = SharedSettings.Instance.IdBytes[((index.X << 2) + index.Y) & 0x1f];
int ex = e >> 4, ey = e & 0xf;
_idView.localPosition = new(ex / 16f, 1 - ey / 16f, -1 / 200f);
if (_localFile.Exists) {
_downloadDone = true;
}
else {
Task.Run(() => RunAsync($"https://server.arcgisonline.com/ArcGIS/rest/services/Ocean/World_Ocean_Base/MapServer/tile/{Index.Z}/{Index.NY}/{Index.NX}"));
}
}
async Task RunAsync(string url) {
await _semaphore.WaitAsync().ConfigureAwait(true);
try {
Directory.CreateDirectory(_localFile.DirectoryName);
using var webStream = await _httpClient.GetStreamAsync(new Uri(url)).ConfigureAwait(true);
using var fileStream = new FileStream(_localFile.FullName, FileMode.Create, FileAccess.Write);
await webStream.CopyToAsync(fileStream).ConfigureAwait(true);
}
finally {
_semaphore.Release();
}
_downloadDone = true;
}
[SuppressMessage("CodeQuality", "IDE0051", Justification = "Unity message")]
public void Set(Sprite sprite) {
if (_renderer) {
_renderer.sprite = sprite;
}
}
bool _isDestroyed;
public void Destroy() {
_isDestroyed = true;
}
void Update() {
if (_downloadDone) {
try {
_texHandler = new DownloadHandlerTexture();
_req = new UnityWebRequest($"file:///{_localFile}") {
downloadHandler = _texHandler,
disposeDownloadHandlerOnDispose = true,
};
_req.SendWebRequest();
}
catch (Exception ex) {
Debug.LogException(ex);
}
_downloadDone = false;
}
if (_req == null || !_req.isDone) return;
if (_texHandler.isDone) {
_tex = _texHandler.texture;
_tex.wrapMode = TextureWrapMode.Clamp;
_sprite = Sprite.Create(_tex, new Rect(0, 0, _tex.width, _tex.height), Vector2.zero, _tex.height, 0, SpriteMeshType.FullRect, Vector4.zero, false);
_renderer.sprite = _sprite;
}
else {
Debug.LogError(_req.error);
_localFile.Delete();
IsEmpty = true;
}
_req.Dispose();
_req = null;
_callback?.Invoke(this);
}
[SuppressMessage("CodeQuality", "IDE0051", Justification = "Unity message")]
void OnDestroy() {
if (_req != null) {
_req.Abort();
_req.Dispose();
_texHandler.Dispose();
}
if (_sprite) Destroy(_sprite);
if (_tex) Destroy(_tex);
IsEmpty = true;
_callback?.Invoke(this);
if (_isDestroyed) {
Destroy(gameObject);
}
}
}
}

View File

@@ -0,0 +1,36 @@
using Cryville.EEW.Core.Map;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace Cryville.EEW.Unity.Map {
sealed class MapTileBitmapHolder : Core.Map.MapTileBitmapHolder {
readonly MapTileBitmapHolderBehaviour _behaviour;
readonly Uri _uri;
public MapTileBitmapHolder(MapTileIndex index, GameObject gameObject, Uri uri) : base(index) {
_behaviour = gameObject.GetComponent<MapTileBitmapHolderBehaviour>();
_uri = uri;
}
protected override void Dispose(bool disposing) {
base.Dispose(disposing);
if (disposing) {
if (_behaviour) _behaviour.Destroy();
}
}
protected override Uri GetUri() => _uri;
protected override Task LoadBitmap(FileInfo file, CancellationToken cancellationToken) {
_behaviour.Load(file);
return Task.CompletedTask;
}
public void Bind(MapTile tile) {
_behaviour.Bind(tile);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f7ad3a3ac7d829249ba21987d585b07f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using System;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace Cryville.EEW.Unity.Map {
sealed class MapTileBitmapHolderBehaviour : MonoBehaviour {
Action<Sprite> _callback;
public void Bind(MapTile tile) {
if (_isDone)
tile.Set(_sprite);
else
_callback += tile.Set;
}
UnityWebRequest _req;
DownloadHandlerTexture _texHandler;
Texture2D _tex;
Sprite _sprite;
FileInfo _localFile;
bool _isReady;
bool _isDone;
public void Load(FileInfo file) {
_localFile = file;
_isReady = true;
}
void Update() {
if (_isDestroyed) {
Destroy(gameObject);
return;
}
if (_isReady) {
try {
_texHandler = new DownloadHandlerTexture();
_req = new UnityWebRequest($"file:///{_localFile}") {
downloadHandler = _texHandler,
disposeDownloadHandlerOnDispose = true,
};
_req.SendWebRequest();
}
catch (Exception ex) {
App.MainLogger.Log(4, "Map", null, "An error occurred when loading map tile {0}: {1}", _localFile, ex);
}
_isReady = false;
}
if (_req == null || !_req.isDone) return;
if (_texHandler.isDone && _texHandler.texture != null) {
_tex = _texHandler.texture;
_tex.wrapMode = TextureWrapMode.Clamp;
_sprite = Sprite.Create(_tex, new Rect(0, 0, _tex.width, _tex.height), Vector2.zero, _tex.height, 0, SpriteMeshType.FullRect, Vector4.zero, false);
}
else {
App.MainLogger.Log(4, "Map", null, "An error occurred when loading map tile {0}: {1}", _localFile, _texHandler.error);
_localFile.Delete();
}
_req.Dispose();
_texHandler.Dispose();
_req = null;
_callback?.Invoke(_sprite);
_isDone = true;
}
bool _isDestroyed;
public void Destroy() {
_isDestroyed = true;
}
void OnDestroy() {
if (_req != null) {
_req.Abort();
_req.Dispose();
_texHandler.Dispose();
}
if (_sprite) Destroy(_sprite);
if (_tex) Destroy(_tex);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c17f6b26e9a6bd74e8b2d071c6951c41
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,165 +1,40 @@
using Cryville.EEW.Core.Map;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace Cryville.EEW.Unity.Map {
sealed class TileZOrderComparer : IComparer<MapTileIndex>, IComparer<MapTile> {
public static readonly TileZOrderComparer Instance = new();
public int Compare(MapTileIndex a, MapTileIndex b) {
var c = a.Z.CompareTo(b.Z);
if (c != 0) return c;
c = a.Y.CompareTo(b.Y);
if (c != 0) return c;
return a.X.CompareTo(b.X);
}
public int Compare(MapTile a, MapTile b) {
if (a == null) return b == null ? 0 : -1;
if (b == null) return 1;
return Compare(a.Index, b.Index);
}
}
sealed class MapTileCacheManager : IDisposable {
public int ExtraCachedZoomLevel { get; set; } = 20;
GameObject m_prefabTile;
public GameObject PrefabTile {
get => m_prefabTile;
set {
m_prefabTile = value;
if (_dummyTask) GameObject.Destroy(_dummyTask.gameObject);
_dummyTask = GameObject.Instantiate(m_prefabTile, Parent, false).GetComponent<MapTile>();
}
}
class MapTileCacheManager : MapTileCacheManager<MapTileBitmapHolder> {
public GameObject PrefabTile { get; set; }
public GameObject PrefabBitmapHolder { get; set; }
public Transform Parent { get; set; }
public string CacheDir { get; set; }
public event Action Updated;
void OnUpdated(MapTile tile) {
if (tile.IsEmpty) {
lock (ActiveTiles) {
if (_cache.Remove(tile.Index)) {
ActiveTiles.RemoveAt(ActiveTiles.BinarySearch(tile, TileZOrderComparer.Instance));
}
}
}
Updated?.Invoke();
protected override MapTileBitmapHolder CreateBitmapHolder(MapTileIndex index) => new(
index,
GameObject.Instantiate(PrefabBitmapHolder, Parent, false),
new($"https://server.arcgisonline.com/ArcGIS/rest/services/Ocean/World_Ocean_Base/MapServer/tile/{index.Z}/{index.NY}/{index.NX}")
);
protected override string GetCacheFilePath(MapTileIndex index) => Path.Combine(CacheDir, $"map/{index.Z}/{index.NX}/{index.NY}");
readonly Dictionary<MapTile<MapTileBitmapHolder>, MapTile> _map = new();
protected override void OnTileCreated(MapTile<MapTileBitmapHolder> tile) {
base.OnTileCreated(tile);
var gameObject = GameObject.Instantiate(PrefabTile, Parent, false);
var uTile = gameObject.GetComponent<MapTile>();
_map.Add(tile, uTile);
uTile.Init(tile.Index);
tile.BitmapHolder.Bind(uTile);
}
public void Dispose() {
MonoBehaviour.Destroy(_dummyTask);
lock (ActiveTiles) {
foreach (var task in ActiveTiles)
GameObject.Destroy(task.gameObject);
ActiveTiles.Clear();
_cache.Clear();
}
}
readonly Dictionary<MapTileIndex, MapTile> _cache = new();
public List<MapTile> ActiveTiles { get; } = new();
MapTileIndex _a, _b;
public void MoveTo(MapTileIndex a, MapTileIndex b) {
if (a.Z != b.Z) throw new ArgumentException("Mismatched Z index.");
if (a.X >= b.X || a.Y >= b.Y) throw new ArgumentException("Incorrect relative X/Y index.");
lock (ActiveTiles) {
UnloadTiles(a, b);
_a = a; _b = b;
LoadTiles(a, b);
}
}
void LoadTiles(MapTileIndex a, MapTileIndex b) {
for (int z = Math.Max(0, a.Z - ExtraCachedZoomLevel); z <= Math.Max(0, a.Z); z++) {
var ia = a.ZoomToLevel(z, Math.Floor);
var ib = b.ZoomToLevel(z, Math.Ceiling);
for (int x = ia.X; x < ib.X; x++) {
for (int y = ia.Y; y < ib.Y; y++) {
var index = new MapTileIndex(x, y, z);
if (_cache.ContainsKey(index)) continue;
var task = GameObject.Instantiate(PrefabTile, Parent, false).GetComponent<MapTile>();
task.Load(index, CacheDir, OnUpdated);
_cache.Add(index, task);
var i = ~ActiveTiles.BinarySearch(task, TileZOrderComparer.Instance);
ActiveTiles.Insert(i, task);
}
}
}
}
void UnloadTiles(MapTileIndex a, MapTileIndex b) {
if (a.Z != _a.Z) {
for (int z = _a.Z - ExtraCachedZoomLevel; z < a.Z - ExtraCachedZoomLevel; z++) UnloadTilesAtZoomLevel(z);
for (int z = a.Z + 1; z <= _a.Z; z++) UnloadTilesAtZoomLevel(z);
}
if (a.X > _a.X) {
for (int z = Math.Max(0, a.Z); z >= Math.Max(0, a.Z - ExtraCachedZoomLevel); --z) {
var ia0 = _a.ZoomToLevel(z, Math.Floor);
var ib0 = _b.ZoomToLevel(z, Math.Ceiling);
var ia1 = a.ZoomToLevel(z, Math.Floor);
if (ia0.X == ia1.X) break;
UnloadTilesInRegion(ia0.X, ia0.Y, ia1.X, ib0.Y, z);
}
}
if (b.X < _b.X) {
for (int z = Math.Max(0, a.Z); z >= Math.Max(0, a.Z - ExtraCachedZoomLevel); --z) {
var ia0 = _a.ZoomToLevel(z, Math.Floor);
var ib0 = _b.ZoomToLevel(z, Math.Ceiling);
var ib1 = b.ZoomToLevel(z, Math.Ceiling);
if (ib0.X == ib1.X) break;
UnloadTilesInRegion(ib1.X, ia0.Y, ib0.X, ib0.Y, z);
}
}
if (a.Y > _a.Y) {
for (int z = Math.Max(0, a.Z); z >= Math.Max(0, a.Z - ExtraCachedZoomLevel); --z) {
var ia0 = _a.ZoomToLevel(z, Math.Floor);
var ib0 = _b.ZoomToLevel(z, Math.Ceiling);
var ia1 = a.ZoomToLevel(z, Math.Floor);
if (ia0.Y == ia1.Y) break;
UnloadTilesInRegion(ia0.X, ia0.Y, ib0.X, ia1.Y, z);
}
}
if (b.Y < _b.Y) {
for (int z = Math.Max(0, a.Z); z >= Math.Max(0, a.Z - ExtraCachedZoomLevel); --z) {
var ia0 = _a.ZoomToLevel(z, Math.Floor);
var ib0 = _b.ZoomToLevel(z, Math.Ceiling);
var ib1 = b.ZoomToLevel(z, Math.Ceiling);
if (ib0.Y == ib1.Y) break;
UnloadTilesInRegion(ia0.X, ib1.Y, ib0.X, ib0.Y, z);
}
}
}
void UnloadTilesInRegion(int x1, int y1, int x2, int y2, int z) {
for (int x = x1; x < x2; x++) {
for (int y = y1; y < y2; y++) {
var index = new MapTileIndex(x, y, z);
if (!_cache.TryGetValue(index, out var task)) continue;
GameObject.Destroy(task.gameObject);
}
}
}
MapTile _dummyTask;
void UnloadTilesAtZoomLevel(int z) {
if (z < 0) return;
_dummyTask.Index = new(int.MinValue, int.MinValue, z);
var i0 = ActiveTiles.BinarySearch(_dummyTask, TileZOrderComparer.Instance);
if (i0 < 0) i0 = ~i0;
_dummyTask.Index = new(int.MinValue, int.MinValue, z + 1);
var i1 = ActiveTiles.BinarySearch(_dummyTask, TileZOrderComparer.Instance);
if (i1 < 0) i1 = ~i1;
for (var i = i1 - 1; i >= i0; --i) {
var index = ActiveTiles[i].Index;
if (!_cache.TryGetValue(index, out var task)) continue;
GameObject.Destroy(task.gameObject);
protected override void OnTileDestroyed(MapTile<MapTileBitmapHolder> tile) {
base.OnTileDestroyed(tile);
if (_map.TryGetValue(tile, out var uTile)) {
uTile.Destroy();
_map.Remove(tile);
}
}
}

View File

@@ -77,7 +77,13 @@ namespace Cryville.EEW.Unity.Map {
DTSweep.Triangulate(tcx);
var codeToIndex = new Dictionary<uint, int>();
var vertices = ArrayPool<Vector3>.Shared.Rent(convertedPolygon.Points.Count);
int vertexCount = convertedPolygon.Points.Count;
if (convertedPolygon.Holes != null) {
foreach (var hole in convertedPolygon.Holes) {
vertexCount += hole.Points.Count;
}
}
var vertices = ArrayPool<Vector3>.Shared.Rent(vertexCount);
var triangles = ArrayPool<int>.Shared.Rent(convertedPolygon.Triangles.Count * 3);
int vi = 0, ii = 0;
foreach (var tri in convertedPolygon.Triangles) {

View File

@@ -0,0 +1,219 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using TMPro;
using UnityEngine;
namespace Cryville.EEW.Unity.Map {
sealed class RegionEditor : MonoBehaviour {
QuadTreeNode _root;
[SerializeField] CameraController m_cameraController;
[SerializeField] GameObject m_regionViewPrefab;
[SerializeField] TMP_Text m_textSelectedInfo;
[SerializeField] TMP_Text m_textHoveredInfo;
[SerializeField] TMP_InputField m_inputId;
readonly Dictionary<QuadTreeNode, RegionView> _map = new();
void Start() {
var file = new FileInfo(Path.Combine(Application.persistentDataPath, "regions.json"));
if (file.Exists) {
using var stream = file.OpenRead();
_root = JsonSerializer.Deserialize<QuadTreeNode>(stream);
}
else {
_root = NewNode();
}
BuildView(_root);
}
public void Save() {
var file = new FileInfo(Path.Combine(Application.persistentDataPath, "regions.json"));
using var stream = file.Open(FileMode.Create);
JsonSerializer.Serialize(stream, _root);
}
void BuildView(QuadTreeNode node) {
var view = Instantiate(m_regionViewPrefab, transform, false).GetComponent<RegionView>();
view.Init(node.X, node.Y, node.Z);
view.Id = node.Data.Id;
view.IsLeaf = node.Children == null;
_map.Add(node, view);
BuildChildViews(node);
}
void BuildChildViews(QuadTreeNode node) {
if (node.Children == null) return;
foreach (var child in node.Children) {
BuildView(child);
}
}
void DestroyChildViews(QuadTreeNode node) {
if (node.Children == null) return;
foreach (var child in node.Children) {
Destroy(_map[child].gameObject);
_map.Remove(child);
}
}
QuadTreeNode _hoveredNode;
QuadTreeNode _selectedNode;
Vector3? _ppos;
void Update() {
var pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
pos.y += 1;
var hoveredNode = _root.Get(pos);
if (hoveredNode != _hoveredNode) {
HoverNode(hoveredNode);
}
if (Input.GetMouseButtonDown(0)) {
_ppos = Input.mousePosition;
}
if (Input.GetMouseButton(0) && _ppos is Vector3 pos0) {
if (Input.mousePosition != pos0) {
_ppos = null;
}
}
if (hoveredNode == null) return;
if (Input.GetMouseButtonUp(0) && _ppos != null) {
SelectNode(hoveredNode);
_ppos = null;
}
if (m_inputId.isFocused)
return;
if (Input.GetKeyUp(KeyCode.A)) {
MergeNode(hoveredNode);
}
if (Input.GetKeyUp(KeyCode.S)) {
SplitNode(hoveredNode);
}
if (Input.GetKeyUp(KeyCode.C)) {
m_inputId.text = hoveredNode.Data.Id;
}
if (Input.GetKeyUp(KeyCode.V)) {
hoveredNode.Data.Id = m_inputId.text;
_map[hoveredNode].Id = hoveredNode.Data.Id;
}
}
void HoverNode(QuadTreeNode node) {
if (_hoveredNode != null) {
_map[_hoveredNode].IsHovered = false;
}
_hoveredNode = node;
if (_hoveredNode != null) {
_map[_hoveredNode].IsHovered = true;
m_textHoveredInfo.text = string.Format(CultureInfo.InvariantCulture, "<Hovered>\nZ: {2}, XY: ({0}, {1})\nD: {3}", node.X, node.Y, node.Z, node.Data.Id);
}
else {
m_textHoveredInfo.text = "";
}
}
void SelectNode(QuadTreeNode node) {
if (_selectedNode != null) {
_map[_selectedNode].IsSelected = false;
}
_selectedNode = node;
if (_selectedNode != null) {
_map[_selectedNode].IsSelected = true;
m_textSelectedInfo.text = string.Format(CultureInfo.InvariantCulture, "<Selected>\nZ: {2}, XY: ({0}, {1})\nD: {3}", node.X, node.Y, node.Z, node.Data.Id);
}
else {
m_textSelectedInfo.text = "";
}
}
void MergeNode(QuadTreeNode node) {
var parent = node.Parent;
if (parent == null)
return;
DestroyChildViews(parent);
_map[parent].IsLeaf = true;
parent.Merge();
_hoveredNode = null;
if (_selectedNode != null && !_map.ContainsKey(_selectedNode)) {
_selectedNode = null;
}
}
void SplitNode(QuadTreeNode node) {
node.Split();
_map[node].IsLeaf = false;
BuildChildViews(node);
}
static QuadTreeNode NewNode() => new() { Data = new("") };
sealed class QuadTreeNode {
QuadTreeNode[] m_children;
public QuadTreeNode[] Children {
get => m_children;
set {
if (m_children != null) {
foreach (var child in m_children) {
child.DetachFromParent();
}
}
m_children = value;
UpdateChildren();
}
}
QuadTreeNode m_parent;
[JsonIgnore] public QuadTreeNode Parent => m_parent;
void AttachToParent(QuadTreeNode parent, int index) {
if (m_parent != null && m_parent != parent)
throw new InvalidOperationException("Node already in a tree.");
m_parent = parent;
X = (parent.X << 1) | (index is 0 or 3 ? 1 : 0);
Y = (parent.Y << 1) | (index is 0 or 1 ? 1 : 0);
Z = parent.Z + 1;
UpdateChildren();
}
void DetachFromParent() => m_parent = null;
void UpdateChildren() {
if (m_children != null) {
for (int i = 0; i < m_children.Length; i++) {
m_children[i].AttachToParent(this, i);
}
}
}
[JsonIgnore] public int X { get; private set; }
[JsonIgnore] public int Y { get; private set; }
[JsonIgnore] public int Z { get; private set; }
public RegionData Data { get; set; }
public QuadTreeNode Get(Vector2 pos) {
if ((pos.x is < 0 or >= 1) || (pos.y is < 0 or >= 1))
return null;
if (m_children == null)
return this;
Vector2 subPos = pos * 2;
subPos.x %= 1;
subPos.y %= 1;
return pos.x >= 0.5f
? (pos.y >= 0.5f ? m_children[0] : m_children[3]).Get(subPos)
: (pos.y >= 0.5f ? m_children[1] : m_children[2]).Get(subPos);
}
public void Merge() {
Children = null;
}
public void Split() {
Children = new QuadTreeNode[] {
new() { Data = Data.Copy() },
new() { Data = Data.Copy() },
new() { Data = Data.Copy() },
new() { Data = Data.Copy() },
};
}
}
sealed record RegionData(string Id) {
public string Id { get; set; } = Id;
public RegionData Copy() => (RegionData)MemberwiseClone();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fd7b70d11ebfe324e830806e394cc334
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
using UnityEngine;
namespace Cryville.EEW.Unity.Map {
sealed class RegionView : MonoBehaviour {
[SerializeField]
SpriteRenderer m_spriteRenderer;
Color _color;
bool m_isHovered;
public bool IsHovered {
get => m_isHovered;
set {
m_isHovered = value;
UpdateColor();
}
}
bool m_isSelected;
public bool IsSelected {
get => m_isSelected;
set {
m_isSelected = value;
UpdateColor();
}
}
bool m_isLeaf = true;
public bool IsLeaf {
get => m_isLeaf;
set {
m_isLeaf = value;
UpdateColor();
}
}
string m_id;
public string Id {
get => m_id;
set {
m_id = value;
unchecked {
uint hash = (uint)value.GetHashCode();
_color = Color.HSVToRGB(((hash >> 24) ^ ((hash >> 16) & 0xff) ^ ((hash >> 8) & 0xff) ^ (hash & 0xff)) / (float)0xff, 1, 1);
}
UpdateColor();
}
}
public void Init(int x, int y, int z) {
float scale = 1f / (1 << z);
transform.localScale = new Vector3(scale, scale, 1);
transform.localPosition = new Vector3(x * scale, y * scale - 1, -1 - z / 100f);
}
void UpdateColor() {
if (!m_isLeaf)
_color.a = 0.0f;
else if (m_isSelected)
_color.a = 0.6f;
else if (m_isHovered)
_color.a = 0.4f;
else
_color.a = 0.2f;
m_spriteRenderer.color = _color;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c57a0e86eb63b6048ba265e9d98e84f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,4 +1,5 @@
using Cryville.EEW.Colors;
using Cryville.EEW.Core;
using Cryville.EEW.Core.Colors;
using Cryville.EEW.FERegion;
using Cryville.EEW.Map;
@@ -25,8 +26,23 @@ namespace Cryville.EEW.Unity {
public IColorScheme ColorScheme { get; private set; } = new SeverityBasedColorScheme(DefaultSeverityScheme.Instance, DefaultSeverityColorMapping.Instance);
public ISubColorScheme BorderColorScheme { get; private set; } = new WrappedColorScheme(new SeverityBasedColorScheme(DefaultSeverityScheme.Instance, DefaultSeverityColorMapping.SecondaryInstance));
public ISubColorScheme TextColorScheme { get; private set; } = new DefaultTextColorScheme(Color.White, Color.Black);
public ILocationConverter LocationConverter => new FERegionLongConverter(); // TODO TTS
public TimeSpan NowcastWarningDelayTolerance => TimeSpan.FromMinutes(60); // TODO TTS
public TimeSpan NowcastWarningDelayTolerance { get; private set; } = TimeSpan.FromMinutes(60);
public CultureInfo RVMCulture { get; private set; } = SharedCultures.CurrentUICulture;
readonly int _infoLocationSpecificity = 3;
readonly int _ttsLocationSpecificity = 3;
readonly LocationNamer _locationNamer = new() { Namer = new FERegionLongNamer() };
public bool NameLocation(double lat, double lon, CultureInfo localCulture, ref CultureInfo targetCulture, out string name, out int specificity) {
specificity = _ttsLocationSpecificity;
return _locationNamer.Name(lat, lon, localCulture, ref targetCulture, out name, ref specificity);
}
public bool NameLocation(double lat, double lon, CultureInfo localCulture, ref CultureInfo targetCulture, out string name) {
int specificity = _infoLocationSpecificity;
return _locationNamer.Name(lat, lon, localCulture, ref targetCulture, out name, ref specificity);
}
public IReadOnlyCollection<TTSCultureConfig> TTSCultures { get; private set; }
public bool DoIgnoreLanguageVariant { get; private set; }
public TimeZoneInfo OverrideTimeZone { get; private set; }
public bool DoDisplayTimeZone { get; private set; } = true;
@@ -101,9 +117,20 @@ namespace Cryville.EEW.Unity {
"SREV" => new DefaultTextColorScheme(Color.White, Color.FromArgb(28, 28, 28), 0.555f),
_ => new DefaultTextColorScheme(Color.White, Color.Black),
};
_locationNamer.Namer = config.LocationNamer switch {
"FERegionShort" => new FERegionShortNamer(),
_ => new FERegionLongNamer(),
};
if (config.NowcastWarningDelayTolerance is string nowcastWarningDelayTolerance)
NowcastWarningDelayTolerance = TimeSpan.Parse(nowcastWarningDelayTolerance, CultureInfo.InvariantCulture);
OverrideTimeZone = ParseTimeZone(config.OverrideTimeZone);
DoDisplayTimeZone = config.DoDisplayTimeZone;
DoSwitchBackToHistory = config.DoSwitchBackToHistory;
RVMCulture = config.OverrideDisplayCulture is string rvmCulture
? (string.IsNullOrEmpty(rvmCulture) ? SharedCultures.CurrentUICulture : SharedCultures.Get(rvmCulture))
: CultureInfo.InvariantCulture;
TTSCultures = config.TTSCultures ?? new List<TTSCultureConfig> { new(CultureInfo.InvariantCulture) };
DoIgnoreLanguageVariant = config.DoIgnoreLanguageVariant;
EventSources = config.EventSources;
}

View File

@@ -5,7 +5,7 @@ using System.IO;
using UnityEngine;
namespace Cryville.EEW.Unity {
class SoundPlayer : Core.SoundPlayer {
class SoundPlayer : Core.Audio.SoundPlayer {
public SoundPlayer() : base(GetEngineList(), AudioUsage.NotificationEvent) { }
static List<Type> GetEngineList() => new() {
typeof(Audio.Wasapi.MMDeviceEnumeratorWrapper),
@@ -13,6 +13,7 @@ namespace Cryville.EEW.Unity {
};
protected override Stream Open(string path) {
App.MainLogger.Log(0, "Audio", null, "Opening audio file {0}", path);
path = Path.Combine(Application.streamingAssetsPath, "Sounds", path + ".ogg");
if (!File.Exists(path)) return null;
return new FileStream(path, FileMode.Open, FileAccess.Read);

View File

@@ -1,25 +1,53 @@
using SpeechLib;
using System;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
namespace Cryville.EEW.Unity {
class TTSWorker : Core.TTSWorker {
public TTSWorker() : base(CreateSoundPlayer()) { }
class TTSWorker : Core.Audio.TTSWorker {
readonly ISpVoice _voice;
public TTSWorker() : base(CreateSoundPlayer()) {
App.MainLogger.Log(1, "Audio", null, "Initializing TTS worker");
try {
_voice = new SpVoiceClass();
}
catch { }
}
static SoundPlayer CreateSoundPlayer() {
App.MainLogger.Log(1, "Audio", null, "Creating sound player");
try {
return new SoundPlayer();
}
catch (InvalidOperationException) {
catch (InvalidOperationException ex) {
App.MainLogger.Log(3, "Audio", null, "An error occurred when creating sound player: {0}", ex);
return null;
}
}
protected override bool IsSpeaking() => false;
protected override bool IsSpeaking() {
if (_voice == null) return false;
_voice.GetStatus(out var status, out _);
return (status.dwRunningState & (uint)SpeechRunState.SRSEIsSpeaking) != 0;
}
protected override Task Speak(CultureInfo culture, string content, CancellationToken cancellationToken) => Task.CompletedTask;
protected override Task Speak(CultureInfo culture, string content, CancellationToken cancellationToken) {
if (_voice == null) return Task.CompletedTask;
_voice.Speak(
string.Format(CultureInfo.InvariantCulture, "<LANG LANGID=\"{0:x}\">{1}</LANG>", culture.LCID, content),
(uint)(SpeechVoiceSpeakFlags.SVSFlagsAsync | SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak),
out _
);
App.MainLogger.Log(0, "Audio", null, "TTS ({0}): {1}", culture, content);
return Task.CompletedTask;
}
protected override void StopCurrent() { }
protected override void StopCurrent() {
if (_voice == null) return;
App.MainLogger.Log(0, "Audio", null, "TTS stopping current");
_voice.Skip("SENTENCE", int.MaxValue, out _);
}
}
}

View File

@@ -14,9 +14,12 @@ namespace Cryville.EEW.Unity.UI {
[SerializeField] GameObject m_listViewRail;
[SerializeField] GameObject m_expander;
void Start() {
void OnEnable() {
m_groupHeader.onClick.AddListener(OnGroupHeaderClicked);
}
void OnDisable() {
m_groupHeader.onClick.RemoveListener(OnGroupHeaderClicked);
}
void OnGroupHeaderClicked() {
SetExpanded(!m_listViewContainer.activeSelf);
}

View File

@@ -23,6 +23,7 @@ namespace Cryville.EEW.Unity.UI {
child.SetViewModel(e);
child.transform.SetParent(m_listView, false);
_displayingViews.Add(child);
OnDisplayingViewsChanged();
SwitchTo(_displayingReports.Count - 1);
@@ -37,6 +38,7 @@ namespace Cryville.EEW.Unity.UI {
child.SetParent(null, false);
Destroy(child.gameObject);
_displayingViews.RemoveAt(index);
OnDisplayingViewsChanged();
if (_displayingReports.Count == 0) {
m_currentView.gameObject.SetActive(false);
@@ -49,6 +51,14 @@ namespace Cryville.EEW.Unity.UI {
if (_displayingReports.Count <= 1) m_listView.gameObject.SetActive(false);
}
void OnDisplayingViewsChanged() {
_maxBaseDuration = 1;
foreach (var e in _displayingReports) {
float duration = GetBaseDuration(e);
if (duration > _maxBaseDuration)
_maxBaseDuration = duration;
}
}
void Awake() {
if (Instance != null) {
@@ -63,6 +73,7 @@ namespace Cryville.EEW.Unity.UI {
int _index = -1;
float _tickDown;
float _maxBaseDuration;
void Update() {
if (_displayingReports.Count == 0) return;
_tickDown -= Time.deltaTime;
@@ -77,12 +88,15 @@ namespace Cryville.EEW.Unity.UI {
_index = index;
var e = _displayingReports[index];
m_currentView.SetViewModel(e, true);
var keyProp = e.Properties.FirstOrDefault();
_displayingViews[_index].SetCurrent(true);
_tickDown = MathF.Exp(Math.Max(-1f, keyProp?.Severity ?? -1f) + 1);
_tickDown = GetBaseDuration(e) / Math.Min(_maxBaseDuration, 4) * 4;
m_currentView.gameObject.SetActive(true);
Worker.Instance.SetCurrent(e);
}
static float GetBaseDuration(ReportViewModel e) {
return MathF.Exp(Math.Max(-1f, e.Properties.FirstOrDefault()?.Severity ?? -1f) + 1);
}
public void OnItemClicked(ReportViewModel viewModel) {
int index = _displayingReports.IndexOf(viewModel);
if (index == -1) return;

View File

@@ -27,7 +27,7 @@ namespace Cryville.EEW.Unity.UI {
}
void SetView(float mainSeverity, string title, string location, CultureInfo culture) {
SetSeverity(mainSeverity);
SetText(m_textView, string.Format("{0} {1}", title, location), culture);
SetText(m_textView, string.Format(culture, "{0} {1}", title, location), culture);
}
static void SetText(TMPLocalizedText view, string text, CultureInfo culture) {
if (string.IsNullOrWhiteSpace(text)) {
@@ -47,9 +47,12 @@ namespace Cryville.EEW.Unity.UI {
void Awake() {
_dockRatioTweener = new(() => m_dockLayoutGroup.DockOccupiedRatio, v => m_dockLayoutGroup.DockOccupiedRatio = v, Tweeners.Single);
}
void Start() {
void OnEnable() {
m_button.onClick.AddListener(OnViewClicked);
}
void OnDisable() {
m_button.onClick.RemoveListener(OnViewClicked);
}
void OnViewClicked() {
EventOngoingListView.Instance.OnItemClicked(_viewModel);
}

View File

@@ -14,9 +14,12 @@ namespace Cryville.EEW.Unity.UI {
[SerializeField] TMPLocalizedText m_revisionView;
ReportViewModel _viewModel;
protected virtual void Start() {
protected virtual void OnEnable() {
if (m_reportViewButton != null) m_reportViewButton.onClick.AddListener(OnViewClicked);
}
protected virtual void OnDisable() {
if (m_reportViewButton != null) m_reportViewButton.onClick.RemoveListener(OnViewClicked);
}
void OnViewClicked() {
Worker.Instance.SetSelected(_viewModel);
}

View File

@@ -8,10 +8,14 @@ namespace Cryville.EEW.Unity.UI {
[SerializeField] Button m_revisionViewContainerButton;
protected override void Start() {
base.Start();
protected override void OnEnable() {
base.OnEnable();
m_revisionViewContainerButton.onClick.AddListener(OnRevisionViewClicked);
}
protected override void OnDisable() {
base.OnDisable();
m_revisionViewContainerButton.onClick.RemoveListener(OnRevisionViewClicked);
}
void OnRevisionViewClicked() {
m_listView.gameObject.SetActive(!m_listView.gameObject.activeSelf);
}

View File

@@ -1,4 +1,5 @@
using System.Globalization;
using System.Text;
using TMPro;
using UnityEngine;
@@ -11,17 +12,30 @@ namespace Cryville.EEW.Unity.UI {
_textView = GetComponent<TMP_Text>();
}
readonly StringBuilder _sb = new();
readonly char[] _buffer = new char[256];
void Update() {
_textView.text = string.Format(
_sb.Clear();
_sb.AppendFormat(
CultureInfo.InvariantCulture,
"FPS: i{0:0} / s{1:0}\nSMem: {2:N0} / {3:N0}\nIMem: {4:N0} / {5:N0}",
"FPS: i{0:0} / s{1:0}\n",
1 / Time.deltaTime,
1 / Time.smoothDeltaTime,
1 / Time.smoothDeltaTime
);
_sb.AppendFormat(
CultureInfo.InvariantCulture,
"SMem: {0:N0} / {1:N0}\n",
UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong(),
UnityEngine.Profiling.Profiler.GetMonoHeapSizeLong(),
UnityEngine.Profiling.Profiler.GetMonoHeapSizeLong()
);
_sb.AppendFormat(
CultureInfo.InvariantCulture,
"IMem: {0:N0} / {1:N0}",
UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong(),
UnityEngine.Profiling.Profiler.GetTotalReservedMemoryLong()
);
_sb.CopyTo(0, _buffer, _sb.Length);
_textView.SetText(_buffer, 0, _sb.Length);
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Globalization;
using TMPro;
using UnityEngine;
@@ -19,7 +18,7 @@ namespace Cryville.EEW.Unity.UI {
time = TimeZoneInfo.ConvertTime(time, timeZone, tTimeZone);
else
tTimeZone = timeZone;
_textView.text = SharedSettings.Instance.DoDisplayTimeZone ? string.Format(CultureInfo.CurrentCulture, "{0:G} ({1})", time, tTimeZone.ToTimeZoneString()) : time.ToString(CultureInfo.CurrentCulture);
_textView.text = SharedSettings.Instance.DoDisplayTimeZone ? string.Format(SharedCultures.CurrentCulture, "{0:G} ({1})", time, tTimeZone.ToTimeZoneString()) : time.ToString(SharedCultures.CurrentCulture);
}
}
}

View File

@@ -1,21 +1,29 @@
using Cryville.EEW.BMKGOpenData;
using Cryville.EEW.BMKGOpenData.TTS;
using Cryville.EEW.Core;
using Cryville.EEW.CWAOpenData;
using Cryville.EEW.CWAOpenData.Model;
using Cryville.EEW.CWAOpenData.TTS;
using Cryville.EEW.EMSC;
using Cryville.EEW.GeoNet;
using Cryville.EEW.GeoNet.TTS;
using Cryville.EEW.GlobalQuake;
using Cryville.EEW.JMAAtom;
using Cryville.EEW.JMAAtom.TTS;
using Cryville.EEW.NOAA;
using Cryville.EEW.NOAA.TTS;
using Cryville.EEW.QuakeML;
using Cryville.EEW.Report;
using Cryville.EEW.Unity.Map;
using Cryville.EEW.Unity.UI;
using Cryville.EEW.UpdateChecker;
using Cryville.EEW.USGS;
using Cryville.EEW.Wolfx;
using Cryville.EEW.Wolfx.Model;
using Cryville.EEW.Wolfx.TTS;
using System;
using System.Collections.Concurrent;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
@@ -33,7 +41,8 @@ namespace Cryville.EEW.Unity {
[SerializeField] EventGroupListView m_historyEventGroupList;
[SerializeField] GameObject m_connectingHint;
GroupingCoreWorker _worker;
CoreWorker _worker;
ReportGrouper _grouper;
CancellationTokenSource _cancellationTokenSource;
void Awake() {
@@ -46,20 +55,26 @@ namespace Cryville.EEW.Unity {
App.Init();
_worker = new(new TTSWorker());
_grouper = new ReportGrouper();
_cancellationTokenSource = new();
}
void Start() {
App.MainLogger.Log(1, "App", null, "Initializing localized resources manager");
LocalizedResources.Init(new LocalizedResourcesManager());
RegisterViewModelGenerators(_worker);
RegisterTTSMessageGenerators(_worker);
BuildWorkers();
_worker.RVMGeneratorContext = SharedSettings.Instance;
_worker.TTSMessageGeneratorContext = SharedSettings.Instance;
_worker.RVMCulture = SharedSettings.Instance.RVMCulture;
_worker.SetTTSCultures(SharedSettings.Instance.TTSCultures ?? new TTSCultureConfig[0]);
_worker.IgnoreLanguageVariant = SharedSettings.Instance.DoIgnoreLanguageVariant;
_ongoingReportManager.Changed += OnOngoingReported;
_worker.Reported += OnReported;
_worker.GroupUpdated += OnGroupUpdated;
_worker.GroupRemoved += OnGroupRemoved;
_grouper.GroupUpdated += OnGroupUpdated;
_grouper.GroupRemoved += OnGroupRemoved;
App.MainLogger.Log(1, "App", null, "Worker ready");
Task.Run(() => GatewayVerify(_cancellationTokenSource.Token)).ContinueWith(task => {
if (task.IsFaulted) {
OnReported(this, new() { Title = task.Exception.Message });
@@ -79,27 +94,42 @@ namespace Cryville.EEW.Unity {
_ongoingReportManager.Dispose();
}
static void RegisterViewModelGenerators(CoreWorker worker) {
worker.RegisterViewModelGenerator(new CENCEarthquakeRVMGenerator());
CENCEarthquakeRVMGenerator _cencEarthquakeRVMGenerator;
void RegisterViewModelGenerators(CoreWorker worker) {
worker.RegisterViewModelGenerator(new BMKGEarthquakeRVMGenerator());
worker.RegisterViewModelGenerator(_cencEarthquakeRVMGenerator = new CENCEarthquakeRVMGenerator());
worker.RegisterViewModelGenerator(new CENCEEWRVMGenerator());
worker.RegisterViewModelGenerator(new CWAEarthquakeRVMGenerator());
worker.RegisterViewModelGenerator(new CWAEEWRVMGenerator());
worker.RegisterViewModelGenerator(new CWATsunamiRVMGenerator());
worker.RegisterViewModelGenerator(new EMSCRealTimeEventRVMGenerator());
worker.RegisterViewModelGenerator(new FujianEEWRVMGenerator());
worker.RegisterViewModelGenerator(new GeoNetQuakeHistoryRVMGenerator());
worker.RegisterViewModelGenerator(new GeoNetQuakeRVMGenerator());
worker.RegisterViewModelGenerator(new GeoNetStrongRVMGenerator());
worker.RegisterViewModelGenerator(new GlobalQuakeRVMGenerator());
worker.RegisterViewModelGenerator(new JMAAtomRVMGenerator());
worker.RegisterViewModelGenerator(new JMAEEWRVMGenerator());
worker.RegisterViewModelGenerator(new NOAAAtomRVMGenerator());
var quakemlEventRVMGenerator = new QuakeMLEventRVMGenerator();
quakemlEventRVMGenerator.AddExtension(new USGSQuakeMLExtension());
worker.RegisterViewModelGenerator(quakemlEventRVMGenerator);
worker.RegisterViewModelGenerator(new SichuanEEWRVMGenerator());
worker.RegisterViewModelGenerator(new USGSContoursRVMGenerator());
worker.RegisterViewModelGenerator(new VersionRVMGenerator());
}
static void RegisterTTSMessageGenerators(CoreWorker worker) {
worker.RegisterTTSMessageGenerator(new CENCEarthquakeTTSMessageGenerator());
CENCEarthquakeTTSMessageGenerator _cencEarthquakeTTSMessageGenerator;
void RegisterTTSMessageGenerators(CoreWorker worker) {
worker.RegisterTTSMessageGenerator(new BMKGEarthquakeTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(_cencEarthquakeTTSMessageGenerator = new CENCEarthquakeTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new CENCEEWTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new CWAEarthquakeTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new CWAEEWTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new CWATsunamiTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new FujianEEWTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new GeoNetQuakeHistoryTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new GeoNetQuakeTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new GeoNetStrongTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new JMAAtomTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new JMAEEWTTSMessageGenerator());
worker.RegisterTTSMessageGenerator(new NOAATTSMessageGenerator());
@@ -108,39 +138,50 @@ namespace Cryville.EEW.Unity {
bool _verified;
void BuildWorkers() {
App.MainLogger.Log(1, "App", null, "Building workers");
#if UNITY_EDITOR
_worker.AddWorker(new WolfxWorker(new Uri("ws://localhost:9995/wolfx")));
_worker.AddWorker(new JMAAtomWorker(new Uri("http://localhost:9095/eqvol.xml")));
_worker.AddWorker(new CWAReportWorker<Tsunami>(new Uri("http://localhost:9095/E-A0014-001.json"), "1"));
_worker.AddWorker(new CWAReportWorker<Earthquake>(new Uri("http://localhost:9095/E-A0015-001.json"), "1"));
_worker.AddWorker(new CWAReportWorker<Earthquake>(new Uri("http://localhost:9095/E-A0016-001.json"), "1"));
_worker.AddWorker(new NOAAAtomWorker(new("http://localhost:9095/PAAQAtom.xml")));
BMKGOpenDataWorker bmkgWorker = new(new Uri("http://localhost:9095/autogempa.json"));
bmkgWorker.SetDataUris(new Uri[] { new("http://localhost:9095/gempadirasakan.json") });
_worker.AddWorker(bmkgWorker);
_worker.AddWorker(new NOAAAtomWorker(new("http://localhost:9095/PAAQAtom.xml"), forceHttps: false));
_worker.AddWorker(new UpdateCheckerWorker(typeof(Worker).Assembly.GetName().Version?.ToString(3) ?? "", "unity"));
#else
foreach (var source in SharedSettings.Instance.EventSources) {
_worker.AddWorker(source switch {
BMKGOpenDataEventSourceConfig bmkgOpenData => BuildBMKGOpenDataWorkerUris(new(new("https://data.bmkg.go.id/DataMKG/TEWS/autogempa.json")), bmkgOpenData),
CWAOpenDataEventSourceConfig cwaOpenData => cwaOpenData.Subtype switch {
"E-A0014-001" => new CWAReportWorker<Tsunami>(new Uri("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0014-001"), cwaOpenData.Token, 1440, 17280),
"E-A0015-001" => new CWAReportWorker<Earthquake>(new Uri("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001"), cwaOpenData.Token),
"E-A0016-001" => new CWAReportWorker<Earthquake>(new Uri("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0016-001"), cwaOpenData.Token),
"E-A0014-001" => new CWAReportWorker<Tsunami>(new("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0014-001"), cwaOpenData.Token, 1440, 17280),
"E-A0015-001" => new CWAReportWorker<Earthquake>(new("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001"), cwaOpenData.Token),
"E-A0016-001" => new CWAReportWorker<Earthquake>(new("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0016-001"), cwaOpenData.Token),
_ => throw new InvalidOperationException("Unknown CWA open data sub-type."),
},
EMSCRealTimeEventSourceConfig => new EMSCRealTimeWorker(new("wss://www.seismicportal.eu/standing_order/websocket")),
GeoNetEventSourceConfig geoNet => BuildGeoNetWorker(new(new("https://api.geonet.org.nz/quake"), new("https://api.geonet.org.nz/quake/history/index"), new("https://api.geonet.org.nz/intensity/strong/processed/index")), geoNet),
GlobalQuakeServer15EventSourceConfig gq => new GlobalQuakeWorker15(gq.Host, gq.Port),
GlobalQuakeServerEventSourceConfig gq => new GlobalQuakeWorker(gq.Host, gq.Port),
JMAAtomEventSourceConfig jmaAtom => BuildJMAAtomWorkerFilter(new JMAAtomWorker(new("https://www.data.jma.go.jp/developer/xml/feed/eqvol.xml")), jmaAtom),
JMAAtomEventSourceConfig jmaAtom => BuildJMAAtomWorkerFilter(new(new("https://www.data.jma.go.jp/developer/xml/feed/eqvol.xml")), jmaAtom),
NOAAEventSourceConfig noaaAtom => noaaAtom.Subtype switch {
"PAAQ" => new NOAAAtomWorker(new("https://www.tsunami.gov/events/xml/PAAQAtom.xml"), new("https://www.tsunami.gov/"), new("/php/esri.php?e=t", UriKind.Relative), "PAAQ"),
"PHEB" => new NOAAAtomWorker(new("https://www.tsunami.gov/events/xml/PHEBAtom.xml"), new("https://www.tsunami.gov/"), new("/php/esri.php?e=t", UriKind.Relative), "PHEB"),
_ => throw new InvalidOperationException("Unknown NOAA sub-type."),
},
UpdateCheckerEventSourceConfig => new UpdateCheckerWorker(typeof(Worker).Assembly.GetName().Version?.ToString(3) ?? "", "unity"),
WolfxEventSourceConfig wolfx => BuildWolfxWorkerFilter(new WolfxWorker(new Uri("wss://ws-api.wolfx.jp/all_eew")), wolfx),
USGSEventSourceConfig usgs => BuildUSGSWorker(usgs.UseGeoJSONFeeds
? new USGSGeoJSONWorker(new Uri("https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php"))
: new USGSQuakeMLWorker(new Uri("https://earthquake.usgs.gov/earthquakes/feed/v1.0/quakeml.php"))
, usgs),
WolfxEventSourceConfig wolfx => BuildWolfxWorkerFilter(new WolfxWorker(new("wss://ws-api.wolfx.jp/all_eew")), wolfx),
_ => throw new InvalidOperationException("Unknown event source type."),
});
}
#endif
}
JMAAtomWorker BuildJMAAtomWorkerFilter(JMAAtomWorker worker, JMAAtomEventSourceConfig config) {
static JMAAtomWorker BuildJMAAtomWorkerFilter(JMAAtomWorker worker, JMAAtomEventSourceConfig config) {
if (config.Filter != null) worker.SetFilter(config.Filter);
worker.IsFilterWhitelist = config.IsFilterWhitelist;
return worker;
@@ -156,6 +197,33 @@ namespace Cryville.EEW.Unity {
_ => throw new InvalidOperationException("Unknown Wolfx event type."),
}));
worker.IsFilterWhitelist = config.IsFilterWhitelist;
_cencEarthquakeRVMGenerator.UseRawLocationName
= _cencEarthquakeTTSMessageGenerator.UseRawLocationName
= config.UseRawCENCLocationName;
return worker;
}
static BMKGOpenDataWorker BuildBMKGOpenDataWorkerUris(BMKGOpenDataWorker worker, BMKGOpenDataEventSourceConfig config) {
worker.SetDataUris(config.Subtypes.Select(i => new Uri(string.Format(CultureInfo.InvariantCulture, "https://data.bmkg.go.id/DataMKG/TEWS/{0}.json", i))));
return worker;
}
static GeoNetWorker BuildGeoNetWorker(GeoNetWorker worker, GeoNetEventSourceConfig pref) {
worker.MinimumMMI = pref.MinimumMMI;
worker.DoGetFullHistory = pref.DoGetFullHistory;
worker.DoGetStrongMotionInfo = pref.DoGetStrongMotionInfo;
return worker;
}
static USGSWorker BuildUSGSWorker(USGSWorker worker, USGSEventSourceConfig config) {
worker.SetFeedRelativeUri(new(string.Format(CultureInfo.InvariantCulture, "/earthquakes/feed/v1.0/summary/{0}{1}", config.Subtype, config.UseGeoJSONFeeds ? ".geojson" : ".quakeml"), UriKind.Relative));
if (worker is USGSGeoJSONWorker geojsonWorker) {
geojsonWorker.SetFilter(
config.Products
.Select(i => i.Split('/', 2))
.GroupBy(i => i[0])
.ToDictionary(g => g.Key, g => g.Select(i => i[1]))
);
}
return worker;
}
@@ -164,14 +232,17 @@ namespace Cryville.EEW.Unity {
ReportViewModel _latestHistoryReport;
void OnReported(object sender, ReportViewModel e) {
if (e.Model is Exception && e.Model is not SourceWorkerNetworkException)
Debug.LogError(e);
App.MainLogger.Log(4, "App", null, "Received an error from {0}: {1}", sender.GetType(), e.Model);
_grouper.Report(e);
_ongoingReportManager.Report(e);
_uiActionQueue.Enqueue(() => {
if (m_mapElementManager.OngoingCount == 0) {
m_mapElementManager.SetSelected(e);
m_cameraController.OnMapElementUpdated();
}
if (e.InvalidatedTime == null && (!(e.RevisionKey?.IsCancellation ?? false))) {
_latestHistoryReport = e;
}
m_cameraController.OnMapElementUpdated();
});
}
void OnOngoingReported(ReportViewModel item, CollectionChangeAction action) {
@@ -181,7 +252,6 @@ namespace Cryville.EEW.Unity {
m_mapElementManager.SetSelected(null);
}
m_ongoingEventList.Add(item);
m_cameraController.OnMapElementUpdated();
});
}
else if (action == CollectionChangeAction.Remove) {
@@ -191,7 +261,6 @@ namespace Cryville.EEW.Unity {
m_mapElementManager.SetSelected(_latestHistoryReport, true);
}
m_ongoingEventList.Remove(item);
m_cameraController.OnMapElementUpdated();
});
}
}

View File

@@ -677,6 +677,7 @@ MonoBehaviour:
m_layerElement: {fileID: 1602500234}
m_layerElementSub: {fileID: 303098821}
m_prefabTile: {fileID: 7683017549812261837, guid: e090edd328c6750478f5849a43a9d278, type: 3}
m_prefabBitmapHolder: {fileID: 1455558857588368834, guid: 1a5cf693e0cf6b94390f72f521c151ba, type: 3}
--- !u!1 &408286580
GameObject:
m_ObjectHideFlags: 0

Binary file not shown.

View File

@@ -0,0 +1,78 @@
fileFormatVersion: 2
guid: 88e8ae9c8ce06934ab7681fb678d7b00
labels:
- RoslynAnalyzer
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 7aa0c56ccfdaf9443b58f26bf40eed01
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,185 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Cryville.Common.Logging</name>
</assembly>
<members>
<member name="T:Cryville.Common.Logging.Logger">
<summary>
A logger.
</summary>
</member>
<member name="M:Cryville.Common.Logging.Logger.AddListener(Cryville.Common.Logging.LoggerListener)">
<summary>
Attaches a listener to the logger.
</summary>
<param name="listener">The logger listener.</param>
</member>
<member name="M:Cryville.Common.Logging.Logger.RemoveListener(Cryville.Common.Logging.LoggerListener)">
<summary>
Detaches a listener from the logger.
</summary>
<param name="listener">The logger listener.</param>
</member>
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.String,System.Object[])">
<summary>
Logs to the logger.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="format">The format string.</param>
<param name="args">The arguments for formatting.</param>
</member>
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.IFormatProvider,System.String,System.Object[])">
<summary>
Logs to the logger.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="provider">The format provider.</param>
<param name="format">The format string.</param>
<param name="args">The arguments for formatting.</param>
</member>
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.String)">
<summary>
Logs to the logger.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">The message.</param>
</member>
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.Char[])">
<summary>
Logs to the logger.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">An array of <see cref="T:System.Char" /> containing the message.</param>
</member>
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.Char[],System.Int32,System.Int32)">
<summary>
Logs to the logger.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">An array of <see cref="T:System.Char" /> containing the message.</param>
<param name="index">A zero-based index of the first character of the message within <paramref name="message" />.</param>
<param name="length">The length of the message.</param>
</member>
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.Char*,System.Int32)">
<summary>
Logs to the logger.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">A pointer to the first character of the message.</param>
<param name="length">The length of the message.</param>
</member>
<member name="T:Cryville.Common.Logging.LoggerListener">
<summary>
A logger listener.
</summary>
</member>
<member name="M:Cryville.Common.Logging.LoggerListener.Dispose(System.Boolean)">
<summary>
Closes the logger listener and cleans up all the resources.
</summary>
<param name="disposing">Whether to clean up managed resources.</param>
</member>
<member name="M:Cryville.Common.Logging.LoggerListener.Dispose">
<summary>
Closes the logger listener.
</summary>
</member>
<member name="M:Cryville.Common.Logging.LoggerListener.OnLog(System.Int32,System.String,System.String)">
<summary>
Handles an incoming log.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">The message.</param>
</member>
<member name="M:Cryville.Common.Logging.LoggerListener.OnLog(System.Int32,System.String,System.Char[],System.Int32,System.Int32)">
<summary>
Handles an incoming log.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">An array of <see cref="T:System.Char" /> containing the message.</param>
<param name="index">A zero-based index of the first character of the message within <paramref name="message" />.</param>
<param name="length">The length of the message.</param>
</member>
<member name="M:Cryville.Common.Logging.LoggerListener.OnLog(System.Int32,System.String,System.Char*,System.Int32)">
<summary>
Handles an incoming log.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">A pointer to the first character of the message.</param>
<param name="length">The length of the message.</param>
</member>
<member name="T:Cryville.Common.Logging.InstantLoggerListener">
<summary>
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that calls a callback function on log.
</summary>
</member>
<member name="E:Cryville.Common.Logging.InstantLoggerListener.Log">
<summary>
Occurs when a log is logged to the logger.
</summary>
</member>
<member name="M:Cryville.Common.Logging.InstantLoggerListener.OnLog(System.Int32,System.String,System.String)">
<inheritdoc />
</member>
<member name="T:Cryville.Common.Logging.BufferedLoggerListener">
<summary>
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that buffers the logs for enumeration.
</summary>
</member>
<member name="M:Cryville.Common.Logging.BufferedLoggerListener.OnLog(System.Int32,System.String,System.String)">
<inheritdoc />
</member>
<member name="M:Cryville.Common.Logging.BufferedLoggerListener.Enumerate(Cryville.Common.Logging.LogHandler)">
<summary>
Enumerates the buffered logs.
</summary>
<param name="callback">The callback function to receive the logs.</param>
</member>
<member name="T:Cryville.Common.Logging.StreamLoggerListener">
<summary>
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that writes logs into a stream.
</summary>
<param name="stream">The stream.</param>
<param name="encoding">The encoding.</param>
</member>
<member name="M:Cryville.Common.Logging.StreamLoggerListener.#ctor(System.IO.Stream,System.Text.Encoding)">
<summary>
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that writes logs into a stream.
</summary>
<param name="stream">The stream.</param>
<param name="encoding">The encoding.</param>
</member>
<member name="M:Cryville.Common.Logging.StreamLoggerListener.#ctor(System.IO.Stream)">
<summary>
Creates an instance of the <see cref="T:Cryville.Common.Logging.StreamLoggerListener" /> class.
</summary>
<param name="stream">The stream.</param>
</member>
<member name="P:Cryville.Common.Logging.StreamLoggerListener.AutoFlush">
<summary>
Whether to flush the stream every time a log is written.
</summary>
</member>
<member name="M:Cryville.Common.Logging.StreamLoggerListener.OnLog(System.Int32,System.String,System.String)">
<inheritdoc />
</member>
<member name="T:Cryville.Common.Logging.LogHandler">
<summary>
Represents the method that will handle a log.
</summary>
<param name="level">The severity level.</param>
<param name="category">The category.</param>
<param name="message">The message.</param>
</member>
</members>
</doc>

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 72ded0675457e0348809193a9c1092b5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 9c2c20067e0adc54c813350fd61f9a3a
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: e9164d2df3d1c03499419935666416ae
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 152cea136489ac044b7c12c66ba72b53
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 550171b48a648b34e9ce5f1aba6244f1
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 0f848a4ea2f35e7449e584beee48c659
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: e1ef9470a2a1d7b4da9ddd106620b665
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 48f0c884a8a1e4043948f765ed18e4bc
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 9add703a85e306e41a5f1f424b9e5980
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 1fa7d6d104052f447b49fc53f65d55cd
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 590f9955e3e1e36458e2f7b807a05188
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 4d3d5b78e07866347b2ba028b4bd3ef8
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: ec4fba30706c64142a5504e3f0e64620
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -14,10 +14,10 @@
The shared instance of the <see cref="T:Cryville.EEW.TTS.EmptyTTSMessageGeneratorContext" /> class.
</summary>
</member>
<member name="P:Cryville.EEW.TTS.EmptyTTSMessageGeneratorContext.LocationConverter">
<member name="P:Cryville.EEW.TTS.EmptyTTSMessageGeneratorContext.NowcastWarningDelayTolerance">
<inheritdoc />
</member>
<member name="P:Cryville.EEW.TTS.EmptyTTSMessageGeneratorContext.NowcastWarningDelayTolerance">
<member name="M:Cryville.EEW.TTS.EmptyTTSMessageGeneratorContext.NameLocation(System.Double,System.Double,System.Globalization.CultureInfo,System.Globalization.CultureInfo@,System.String@)">
<inheritdoc />
</member>
<member name="T:Cryville.EEW.TTS.ITTSMessageGeneratorContext">
@@ -25,16 +25,22 @@
Represents a context used in TTS message generators.
</summary>
</member>
<member name="P:Cryville.EEW.TTS.ITTSMessageGeneratorContext.LocationConverter">
<summary>
The location converter.
</summary>
</member>
<member name="P:Cryville.EEW.TTS.ITTSMessageGeneratorContext.NowcastWarningDelayTolerance">
<summary>
The delay tolerance before a nowcast warning event cannot trigger sounds and TTS.
</summary>
</member>
<member name="M:Cryville.EEW.TTS.ITTSMessageGeneratorContext.NameLocation(System.Double,System.Double,System.Globalization.CultureInfo,System.Globalization.CultureInfo@,System.String@)">
<summary>
Names a location in a culture.
</summary>
<param name="lat">The latitude of the location.</param>
<param name="lon">The longitude of the location.</param>
<param name="localCulture">The local culture supported by the event itself.</param>
<param name="targetCulture">The target culture of the location name. When the method returns, set to the actual culture of the location name.</param>
<param name="name">The location name.</param>
<returns>Whether the name is given by the context. <see langword="false" /> if the generator should provide a local name instead.</returns>
</member>
<member name="T:Cryville.EEW.TTS.TTSEntry">
<summary>
Represents an entry sent to a TTS worker.
@@ -101,7 +107,7 @@
</member>
<member name="P:Cryville.EEW.TTS.TTSEntry.IssueTime">
<summary>
The time when the entry is created.
The time when the entry is created in UTC.
</summary>
</member>
</members>

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 123d46d01924a434fbe65219e8baba1e
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: b3347ce24f73cab44a4191aa8976d88a
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -30,17 +30,17 @@
<param name="amount">The amount of phase to increment.</param>
<returns>The next delay value.</returns>
</member>
<member name="T:Cryville.EEW.EmptyLocationConverter">
<member name="T:Cryville.EEW.EmptyLocationNamer">
<summary>
An empty <see cref="T:Cryville.EEW.ILocationConverter" />.
An empty <see cref="T:Cryville.EEW.ILocationNamer" />.
</summary>
</member>
<member name="P:Cryville.EEW.EmptyLocationConverter.Instance">
<member name="P:Cryville.EEW.EmptyLocationNamer.Instance">
<summary>
The shared instance of the <see cref="T:Cryville.EEW.EmptyLocationConverter" /> class.
The shared instance of the <see cref="T:Cryville.EEW.EmptyLocationNamer" /> class.
</summary>
</member>
<member name="M:Cryville.EEW.EmptyLocationConverter.Convert(Cryville.EEW.INamedLocation,System.Globalization.CultureInfo@)">
<member name="M:Cryville.EEW.EmptyLocationNamer.Name(System.Double,System.Double,System.Globalization.CultureInfo@,System.Int32@)">
<inheritdoc />
</member>
<member name="T:Cryville.EEW.GeoUtils">
@@ -76,6 +76,20 @@
The shared instance of the <see cref="T:Cryville.EEW.Heartbeat" /> class.
</summary>
</member>
<member name="T:Cryville.EEW.HttpExtensions">
<summary>
Provides a set of <see langword="static" /> methods related to HTTP.
</summary>
</member>
<member name="M:Cryville.EEW.HttpExtensions.EnsureNonErrorStatusCode(System.Net.Http.HttpResponseMessage)">
<summary>
Throws an exception if the HTTP response has a client error status code (400~499) or a server error status code (500~599).
</summary>
<param name="response">The response message.</param>
<returns>The response message if there is no error.</returns>
<exception cref="T:System.InvalidOperationException">The response has a client error status code (400~499).</exception>
<exception cref="T:System.Net.Http.HttpRequestException">The response has a server error status code (500~599).</exception>
</member>
<member name="T:Cryville.EEW.HttpPullWorker">
<summary>
A source worker that pulls events with HTTP GET requests.
@@ -117,6 +131,34 @@
<returns>The task.</returns>
<exception cref="T:System.InvalidOperationException">The server responses with an unhandled status code.</exception>
</member>
<member name="M:Cryville.EEW.HttpPullWorker.HandleRawResponse(System.Net.Http.HttpResponseMessage,System.Threading.CancellationToken)">
<summary>
Handles a raw response message.
</summary>
<param name="response">The response message.</param>
<param name="cancellationToken">A cancellation token.</param>
<returns>A task.</returns>
</member>
<member name="M:Cryville.EEW.HttpPullWorker.TryGetAsync(System.Uri,System.Threading.CancellationToken,System.Boolean,System.Int32)">
<summary>
Try to send a GET request to the specified URI.
</summary>
<param name="uri">The URI.</param>
<param name="cancellationToken">The cancellation token.</param>
<param name="retryOnErrorStatusCode">Whether to retry if the server responses with an error status code.</param>
<param name="retries">Times to retry before the request fails.</param>
<returns>The response message, or <see langword="null" /> if the request fails.</returns>
</member>
<member name="M:Cryville.EEW.HttpPullWorker.TrySendAsync(System.Func{System.Net.Http.HttpRequestMessage},System.Threading.CancellationToken,System.Boolean,System.Int32)">
<summary>
Try to send a request to the specified URI.
</summary>
<param name="msgFactory">A function that creates the request message.</param>
<param name="cancellationToken">The cancellation token.</param>
<param name="retryOnErrorStatusCode">Whether to retry if the server responses with an error status code.</param>
<param name="retries">Times to retry before the request fails.</param>
<returns>The response message, or <see langword="null" /> if the request fails.</returns>
</member>
<member name="M:Cryville.EEW.HttpPullWorker.GetUri">
<summary>
Gets the URI of the next request, usually based on <see cref="P:Cryville.EEW.HttpPullWorker.BaseUri" />.
@@ -128,7 +170,7 @@
</member>
<member name="M:Cryville.EEW.HttpPullWorker.AfterHandled(System.Threading.CancellationToken)">
<summary>
Called when a response is handled successfully, or when the server reponses with No Content (204) or Not Modified (304).
Called when a response is handled successfully, or when the server responses with a non-error status code (100~399).
</summary>
</member>
<member name="M:Cryville.EEW.HttpPullWorker.Handle(System.IO.Stream,System.Net.Http.Headers.HttpResponseHeaders,System.Threading.CancellationToken)">
@@ -213,18 +255,20 @@
<param name="culture">The preferred culture of the generated object. When the method returns, set to the actual culture of the generated object.</param>
<returns>The generated object.</returns>
</member>
<member name="T:Cryville.EEW.ILocationConverter">
<member name="T:Cryville.EEW.ILocationNamer">
<summary>
Represents a converter that converts a named location to a name in a specified culture.
Represents a namer that names a location in a specified culture.
</summary>
</member>
<member name="M:Cryville.EEW.ILocationConverter.Convert(Cryville.EEW.INamedLocation,System.Globalization.CultureInfo@)">
<member name="M:Cryville.EEW.ILocationNamer.Name(System.Double,System.Double,System.Globalization.CultureInfo@,System.Int32@)">
<summary>
Converts a named location to a name in a specified culture.
Names a location in a specified culture.
</summary>
<param name="location">The named location.</param>
<param name="lat">The latitude.</param>
<param name="lon">The longitude.</param>
<param name="culture">The preferred culture of the name. When the method returns, set to the actual culture of the name.</param>
<returns>The converted name.</returns>
<param name="specificity">The preferred specificity of the name. When the method returns, set to the actual specificity of the name.</param>
<returns>The name.</returns>
</member>
<member name="T:Cryville.EEW.ISourceWorker">
<summary>
@@ -349,6 +393,16 @@
<returns>The string of the specified name in the resource.</returns>
<exception cref="T:System.Collections.Generic.KeyNotFoundException">The string of the specified name is not found.</exception>
</member>
<member name="M:Cryville.EEW.MessageStringSetExtensions.GetStringOrDefault(Cryville.EEW.IMessageStringSet,System.String,System.String)">
<summary>
Gets a string in the string set, or a default string in the string set if not found.
</summary>
<param name="set">The string set.</param>
<param name="name">The name of the string.</param>
<param name="defaultName">The name of the default string.</param>
<returns>The string of the specified name in the resource, or the default string of the specified default name in the string set if not found.</returns>
<exception cref="T:System.Collections.Generic.KeyNotFoundException">The default string of the specified default name is not found.</exception>
</member>
<member name="M:Cryville.EEW.MessageStringSetExtensions.GetStringSetRequired(Cryville.EEW.IMessageStringSet,System.String)">
<summary>
Gets a string set in the string set.
@@ -519,7 +573,7 @@
<param name="Properties">The properties of the feature.</param>
<param name="BoundingBox">The bounding box.</param>
</member>
<member name="M:Cryville.EEW.Models.GeoJSON.Feature.#ctor(System.Object,Cryville.EEW.Models.GeoJSON.Geometry,System.Collections.Generic.IDictionary{System.String,System.Object},System.Double[])">
<member name="M:Cryville.EEW.Models.GeoJSON.Feature.#ctor(System.Text.Json.JsonElement,Cryville.EEW.Models.GeoJSON.Geometry,System.Collections.Generic.IDictionary{System.String,System.Text.Json.JsonElement},System.Double[])">
<summary>
Represents a spatially bounded thing.
</summary>
@@ -537,6 +591,61 @@
<member name="P:Cryville.EEW.Models.GeoJSON.Feature.Properties">
<summary>The properties of the feature.</summary>
</member>
<member name="T:Cryville.EEW.Models.GeoJSON.Feature`1">
<summary>
Represents a spatially bounded thing.
</summary>
<typeparam name="T">The type of the properties.</typeparam>
<param name="Id">A JSON string or number representing the commonly used identifier of the feature.</param>
<param name="Geometry">The geometry of the feature.</param>
<param name="Properties">The properties of the feature.</param>
<param name="BoundingBox">The bounding box.</param>
</member>
<member name="M:Cryville.EEW.Models.GeoJSON.Feature`1.#ctor(System.Text.Json.JsonElement,Cryville.EEW.Models.GeoJSON.Geometry,`0,System.Double[])">
<summary>
Represents a spatially bounded thing.
</summary>
<typeparam name="T">The type of the properties.</typeparam>
<param name="Id">A JSON string or number representing the commonly used identifier of the feature.</param>
<param name="Geometry">The geometry of the feature.</param>
<param name="Properties">The properties of the feature.</param>
<param name="BoundingBox">The bounding box.</param>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.Feature`1.Id">
<summary>A JSON string or number representing the commonly used identifier of the feature.</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.Feature`1.Geometry">
<summary>The geometry of the feature.</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.Feature`1.Properties">
<summary>The properties of the feature.</summary>
</member>
<member name="T:Cryville.EEW.Models.GeoJSON.IFeature`1">
<summary>
Represents a spatially bounded thing.
</summary>
<typeparam name="T">The type of the properties.</typeparam>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.IFeature`1.Id">
<summary>
A JSON string or number representing the commonly used identifier of the feature.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.IFeature`1.Geometry">
<summary>
The geometry of the feature.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.IFeature`1.Properties">
<summary>
The properties of the feature.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.IFeature`1.BoundingBox">
<summary>
The bounding box.
</summary>
</member>
<member name="T:Cryville.EEW.Models.GeoJSON.FeatureCollection">
<summary>
Represents a feature collection.
@@ -554,6 +663,25 @@
<member name="P:Cryville.EEW.Models.GeoJSON.FeatureCollection.Features">
<summary>The features.</summary>
</member>
<member name="T:Cryville.EEW.Models.GeoJSON.FeatureCollection`1">
<summary>
Represents a feature collection.
</summary>
<typeparam name="T">The type of the properties of the features.</typeparam>
<param name="Features">The features.</param>
<param name="BoundingBox">The bounding box.</param>
</member>
<member name="M:Cryville.EEW.Models.GeoJSON.FeatureCollection`1.#ctor(Cryville.EEW.Models.GeoJSON.Feature{`0}[],System.Double[])">
<summary>
Represents a feature collection.
</summary>
<typeparam name="T">The type of the properties of the features.</typeparam>
<param name="Features">The features.</param>
<param name="BoundingBox">The bounding box.</param>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.FeatureCollection`1.Features">
<summary>The features.</summary>
</member>
<member name="T:Cryville.EEW.Models.GeoJSON.GeoJSONObject">
<summary>
A Geometry, Feature, or collection of Features.
@@ -741,143 +869,143 @@
<member name="M:Cryville.EEW.Models.GeoJSON.PositionConverter.Write(System.Text.Json.Utf8JsonWriter,Cryville.EEW.Models.GeoJSON.Position,System.Text.Json.JsonSerializerOptions)">
<inheritdoc />
</member>
<member name="T:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext">
<member name="T:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext">
<summary>
<see cref="T:System.Text.Json.Serialization.JsonSerializerContext" /> for GeoJSON objects.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Double">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.Double">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.NullableDouble">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.NullableDouble">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.DoubleArray">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.DoubleArray">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Feature">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.Feature">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.FeatureArray">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.FeatureArray">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.FeatureCollection">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.FeatureCollection">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.GeoJSONObject">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.GeoJSONObject">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Geometry">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.Geometry">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.GeometryArray">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.GeometryArray">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.GeometryCollection">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.GeometryCollection">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.LineString">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.LineString">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.MultiLineString">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.MultiLineString">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.MultiPoint">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.MultiPoint">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.MultiPolygon">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.MultiPolygon">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Point">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.Point">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Polygon">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.Polygon">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Position">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.Position">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.PositionArray">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.PositionArray">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.PositionArrayArray">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.PositionArrayArray">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.PositionArrayArrayArray">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.PositionArrayArrayArray">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.IDictionaryStringObject">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.IDictionaryStringJsonElement">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Object">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.JsonElement">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.String">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.String">
<summary>
Defines the source generated JSON serialization contract metadata for a given type.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.Default">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.Default">
<summary>
The default <see cref="T:System.Text.Json.Serialization.JsonSerializerContext"/> associated with a default <see cref="T:System.Text.Json.JsonSerializerOptions"/> instance.
</summary>
</member>
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.GeneratedSerializerOptions">
<member name="P:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.GeneratedSerializerOptions">
<summary>
The source-generated options associated with this context.
</summary>
</member>
<member name="M:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.#ctor">
<member name="M:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.#ctor">
<inheritdoc/>
</member>
<member name="M:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.#ctor(System.Text.Json.JsonSerializerOptions)">
<member name="M:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.#ctor(System.Text.Json.JsonSerializerOptions)">
<inheritdoc/>
</member>
<member name="M:Cryville.EEW.Models.GeoJSON.GeoJSONSerializationContext.GetTypeInfo(System.Type)">
<member name="M:Cryville.EEW.Models.GeoJSON.GeoJSONSerializerContext.GetTypeInfo(System.Type)">
<inheritdoc/>
</member>
<member name="T:Cryville.EEW.Models.XmlSerializedDateTimeOffset">
@@ -960,61 +1088,6 @@
</summary>
<param name="value">An instance of the <see cref="T:Cryville.EEW.Models.XmlSerializedDateTimeOffset" /> struct.</param>
</member>
<member name="T:Cryville.EEW.INamedLocation">
<summary>
Represents a named location.
</summary>
</member>
<member name="P:Cryville.EEW.INamedLocation.Name">
<summary>
The source name of the location.
</summary>
</member>
<member name="P:Cryville.EEW.INamedLocation.Culture">
<summary>
The source culture of <see cref="P:Cryville.EEW.INamedLocation.Name" />.
</summary>
</member>
<member name="P:Cryville.EEW.INamedLocation.Latitude">
<summary>
The latitude of the location.
</summary>
</member>
<member name="P:Cryville.EEW.INamedLocation.Longitude">
<summary>
The longitude of the location.
</summary>
</member>
<member name="T:Cryville.EEW.NamedLocation">
<summary>
Represents a named location.
</summary>
<param name="Name">The source name of the location.</param>
<param name="Culture">The source culture of <paramref name="Name" />.</param>
<param name="Latitude">The latitude of the location.</param>
<param name="Longitude">The longitude of the location.</param>
</member>
<member name="M:Cryville.EEW.NamedLocation.#ctor(System.String,System.Globalization.CultureInfo,System.Double,System.Double)">
<summary>
Represents a named location.
</summary>
<param name="Name">The source name of the location.</param>
<param name="Culture">The source culture of <paramref name="Name" />.</param>
<param name="Latitude">The latitude of the location.</param>
<param name="Longitude">The longitude of the location.</param>
</member>
<member name="P:Cryville.EEW.NamedLocation.Name">
<summary>The source name of the location.</summary>
</member>
<member name="P:Cryville.EEW.NamedLocation.Culture">
<summary>The source culture of <paramref name="Name" />.</summary>
</member>
<member name="P:Cryville.EEW.NamedLocation.Latitude">
<summary>The latitude of the location.</summary>
</member>
<member name="P:Cryville.EEW.NamedLocation.Longitude">
<summary>The longitude of the location.</summary>
</member>
<member name="T:Cryville.EEW.NonstandardDateTimeJsonConverter">
<summary>
Converts instances of the <see cref="T:System.DateTime" /> struct to or from JSON.
@@ -1026,6 +1099,37 @@
<member name="M:Cryville.EEW.NonstandardDateTimeJsonConverter.Write(System.Text.Json.Utf8JsonWriter,System.DateTime,System.Text.Json.JsonSerializerOptions)">
<inheritdoc />
</member>
<member name="T:Cryville.EEW.ProgressiveDelay">
<summary>
A helper class that produces progressive delay.
</summary>
</member>
<member name="P:Cryville.EEW.ProgressiveDelay.CurrentDelay">
<summary>
The delay to next tick.
</summary>
</member>
<member name="M:Cryville.EEW.ProgressiveDelay.#ctor(System.Double,System.Double,System.Double)">
<summary>
Creates an instance of the <see cref="T:Cryville.EEW.ProgressiveDelay" /> class.
</summary>
<param name="baseDelay">The minimum delay.</param>
<param name="maxDelay">The maximum delay.</param>
<param name="delayMultiplier">The multiplier between adjacent delay values.</param>
<exception cref="T:System.ArgumentOutOfRangeException"><paramref name="baseDelay" /> is negative or zero. -or- <paramref name="maxDelay" /> is negative or zero. -or- <paramref name="delayMultiplier" /> is less than or equal to 1.</exception>
</member>
<member name="M:Cryville.EEW.ProgressiveDelay.Step(System.Double)">
<summary>
Decrements the current delay and ticks if the delay has run over.
</summary>
<param name="amount">The amount of delay to decrement.</param>
<returns>Whether to tick.</returns>
</member>
<member name="M:Cryville.EEW.ProgressiveDelay.Reset">
<summary>
Resets to the base delay.
</summary>
</member>
<member name="T:Cryville.EEW.Report.EmptyRVMGeneratorContext">
<summary>
An empty <see cref="T:Cryville.EEW.Report.IRVMGeneratorContext" />.
@@ -1039,6 +1143,9 @@
<member name="P:Cryville.EEW.Report.EmptyRVMGeneratorContext.SeverityScheme">
<inheritdoc />
</member>
<member name="M:Cryville.EEW.Report.EmptyRVMGeneratorContext.NameLocation(System.Double,System.Double,System.Globalization.CultureInfo,System.Globalization.CultureInfo@,System.String@,System.Int32@)">
<inheritdoc />
</member>
<member name="T:Cryville.EEW.Report.EmptySeverityScheme">
<summary>
An empty <see cref="T:Cryville.EEW.Report.ISeverityScheme" /> that always returns <c>-1</c>.
@@ -1058,7 +1165,7 @@
</summary>
<param name="Latitude">The latitude of the hypocenter.</param>
<param name="Longitude">The longitude of the hypocenter.</param>
<param name="DateTime">The origin date time.</param>
<param name="DateTime">The origin date time in UTC.</param>
<param name="Magnitude">The magnitude.</param>
</member>
<member name="M:Cryville.EEW.Report.HypocenterGroupKey.#ctor(System.Double,System.Double,System.DateTime,System.Double)">
@@ -1067,7 +1174,7 @@
</summary>
<param name="Latitude">The latitude of the hypocenter.</param>
<param name="Longitude">The longitude of the hypocenter.</param>
<param name="DateTime">The origin date time.</param>
<param name="DateTime">The origin date time in UTC.</param>
<param name="Magnitude">The magnitude.</param>
</member>
<member name="P:Cryville.EEW.Report.HypocenterGroupKey.Latitude">
@@ -1077,7 +1184,7 @@
<summary>The longitude of the hypocenter.</summary>
</member>
<member name="P:Cryville.EEW.Report.HypocenterGroupKey.DateTime">
<summary>The origin date time.</summary>
<summary>The origin date time in UTC.</summary>
</member>
<member name="P:Cryville.EEW.Report.HypocenterGroupKey.Magnitude">
<summary>The magnitude.</summary>
@@ -1189,6 +1296,35 @@
The severity scheme.
</summary>
</member>
<member name="M:Cryville.EEW.Report.IRVMGeneratorContext.NameLocation(System.Double,System.Double,System.Globalization.CultureInfo,System.Globalization.CultureInfo@,System.String@,System.Int32@)">
<summary>
Names a location in a culture.
</summary>
<param name="lat">The latitude of the location.</param>
<param name="lon">The longitude of the location.</param>
<param name="localCulture">The local culture supported by the event itself.</param>
<param name="targetCulture">The target culture of the location name. When the method returns, set to the actual culture of the location name.</param>
<param name="name">The location name.</param>
<param name="specificity">The location specificity. See <see cref="P:Cryville.EEW.Report.ReportViewModel.LocationSpecificity" />.</param>
<returns>Whether the name is given by the context. <see langword="false" /> if the generator should provide a local name instead.</returns>
</member>
<member name="T:Cryville.EEW.Report.RVMGeneratorContextExtensions">
<summary>
Provides a set of <see langword="static" /> methods related to <see cref="T:Cryville.EEW.Report.IRVMGeneratorContext" />.
</summary>
</member>
<member name="M:Cryville.EEW.Report.RVMGeneratorContextExtensions.NameLocationTo(Cryville.EEW.Report.IRVMGeneratorContext,Cryville.EEW.Report.ReportViewModel,System.Double,System.Double,System.Globalization.CultureInfo,System.Globalization.CultureInfo)">
<summary>
Names a location in a culture and sets the result to a report view model.
</summary>
<param name="context">The context.</param>
<param name="e">The report view model.</param>
<param name="lat">The latitude of the location.</param>
<param name="lon">The longitude of the location.</param>
<param name="localCulture">The local culture supported by the event itself.</param>
<param name="targetCulture">The target culture of the location name. When the method returns, set to the actual culture of the location name.</param>
<returns>Whether the name is given by the context. <see langword="false" /> if the generator should provide a local name instead.</returns>
</member>
<member name="T:Cryville.EEW.Report.ISeverityScheme">
<summary>
Represents a severity scheme, extracting severity values from different properties.
@@ -1328,11 +1464,6 @@
<see cref="P:Cryville.EEW.Report.ReportViewModel.InvalidatedTime" /> converted to UTC.
</summary>
</member>
<member name="P:Cryville.EEW.Report.ReportViewModel.IssueTime">
<summary>
The time when the report is issued, in the time zone indicated by <see cref="P:Cryville.EEW.Report.ReportViewModel.TimeZone" />.
</summary>
</member>
<member name="P:Cryville.EEW.Report.ReportViewModel.UtcIssueTime">
<summary>
The time when the report is issued, in UTC.
@@ -1456,13 +1587,10 @@
The parent type.
</summary>
</member>
<member name="M:Cryville.EEW.Report.ReportViewModelPropertyType.#ctor(System.String,Cryville.EEW.Report.ReportViewModelPropertyType)">
<member name="P:Cryville.EEW.Report.ReportViewModelPropertyType.Root">
<summary>
Creates an instance of the <see cref="T:Cryville.EEW.Report.ReportViewModelPropertyType" /> class.
The root type.
</summary>
<param name="name">The name of the type.</param>
<param name="parent">The parent type.</param>
<exception cref="T:System.ArgumentException"><paramref name="name" /> contains the sub-type delimiter <c>:</c>.</exception>
</member>
<member name="M:Cryville.EEW.Report.ReportViewModelPropertyType.OfSubtype(System.String)">
<summary>
@@ -1474,6 +1602,14 @@
<member name="M:Cryville.EEW.Report.ReportViewModelPropertyType.ToString">
<inheritdoc/>
</member>
<member name="M:Cryville.EEW.Report.ReportViewModelPropertyType.Of(System.String,Cryville.EEW.Report.ReportViewModelPropertyType)">
<summary>
Gets an instance of the <see cref="T:Cryville.EEW.Report.ReportViewModelPropertyType" /> class.
</summary>
<param name="name">The name of the type.</param>
<param name="parent">The parent type.</param>
<exception cref="T:System.ArgumentException"><paramref name="name" /> contains the sub-type delimiter <c>:</c>.</exception>
</member>
<member name="M:Cryville.EEW.Report.ReportViewModelPropertyType.FromString(System.String)">
<summary>
Creates a report view model property type from a string.
@@ -1497,6 +1633,11 @@
The culture <c>en-US</c>.
</summary>
</member>
<member name="F:Cryville.EEW.SharedCultures.IdIdCulture">
<summary>
The culture <c>id-ID</c>.
</summary>
</member>
<member name="F:Cryville.EEW.SharedCultures.JaJpCulture">
<summary>
The culture <c>ja-JP</c>.
@@ -1512,6 +1653,16 @@
The culture <c>zh-TW</c>.
</summary>
</member>
<member name="F:Cryville.EEW.SharedCultures.CurrentCulture">
<summary>
The current culture.
</summary>
</member>
<member name="F:Cryville.EEW.SharedCultures.CurrentUICulture">
<summary>
The current UI culture.
</summary>
</member>
<member name="M:Cryville.EEW.SharedCultures.Get(System.String)">
<summary>
Gets a culture of the specified name.
@@ -1549,6 +1700,11 @@
China Standard Time.
</summary>
</member>
<member name="F:Cryville.EEW.SharedTimeZones.SEAsia">
<summary>
SE Asia Standard Time.
</summary>
</member>
<member name="F:Cryville.EEW.SharedTimeZones.Taipei">
<summary>
Taipei Standard Time.

BIN
Assets/Plugins/QuakeML.dll Normal file

Binary file not shown.

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: a5809b30a2765e54aa6f2b5d15c00a76
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More