@sayue_ltr/fleq 1.50.0 → 1.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +47 -5
  3. package/dist/config.js +35 -2
  4. package/dist/dmdata/rest-client.js +58 -3
  5. package/dist/dmdata/telegram-parser.js +37 -59
  6. package/dist/dmdata/ws-client.js +49 -18
  7. package/dist/engine/cli/cli-run.js +71 -1
  8. package/dist/engine/cli/cli.js +12 -0
  9. package/dist/engine/filter/compile-filter.js +21 -0
  10. package/dist/engine/filter/compiler.js +188 -0
  11. package/dist/engine/filter/errors.js +41 -0
  12. package/dist/engine/filter/field-registry.js +78 -0
  13. package/dist/engine/filter/index.js +15 -0
  14. package/dist/engine/filter/parser.js +137 -0
  15. package/dist/engine/filter/rank-maps.js +34 -0
  16. package/dist/engine/filter/tokenizer.js +121 -0
  17. package/dist/engine/filter/type-checker.js +104 -0
  18. package/dist/engine/filter/types.js +2 -0
  19. package/dist/engine/filter-template/pipeline-controller.js +73 -0
  20. package/dist/engine/filter-template/pipeline.js +16 -0
  21. package/dist/engine/messages/display-callbacks.js +7 -0
  22. package/dist/engine/messages/message-router.js +114 -182
  23. package/dist/engine/messages/summary-tracker.js +106 -0
  24. package/dist/engine/messages/telegram-stats.js +103 -0
  25. package/dist/engine/messages/volcano-route-handler.js +122 -0
  26. package/dist/engine/monitor/monitor.js +51 -3
  27. package/dist/engine/monitor/shutdown.js +1 -0
  28. package/dist/engine/notification/notifier.js +16 -1
  29. package/dist/engine/notification/sound-player.js +193 -28
  30. package/dist/engine/presentation/diff-store.js +158 -0
  31. package/dist/engine/presentation/diff-types.js +2 -0
  32. package/dist/engine/presentation/events/from-earthquake.js +53 -0
  33. package/dist/engine/presentation/events/from-eew.js +72 -0
  34. package/dist/engine/presentation/events/from-lg-observation.js +58 -0
  35. package/dist/engine/presentation/events/from-nankai-trough.js +39 -0
  36. package/dist/engine/presentation/events/from-raw.js +35 -0
  37. package/dist/engine/presentation/events/from-seismic-text.js +37 -0
  38. package/dist/engine/presentation/events/from-tsunami.js +51 -0
  39. package/dist/engine/presentation/events/from-volcano.js +88 -0
  40. package/dist/engine/presentation/events/to-presentation-event.js +32 -0
  41. package/dist/engine/presentation/level-helpers.js +118 -0
  42. package/dist/engine/presentation/processors/process-earthquake.js +36 -0
  43. package/dist/engine/presentation/processors/process-eew.js +90 -0
  44. package/dist/engine/presentation/processors/process-lg-observation.js +30 -0
  45. package/dist/engine/presentation/processors/process-message.js +53 -0
  46. package/dist/engine/presentation/processors/process-nankai-trough.js +30 -0
  47. package/dist/engine/presentation/processors/process-raw.js +22 -0
  48. package/dist/engine/presentation/processors/process-seismic-text.js +30 -0
  49. package/dist/engine/presentation/processors/process-tsunami.js +42 -0
  50. package/dist/engine/presentation/processors/process-volcano.js +41 -0
  51. package/dist/engine/presentation/types.js +2 -0
  52. package/dist/engine/startup/config-resolver.js +2 -0
  53. package/dist/engine/template/compile-template.js +18 -0
  54. package/dist/engine/template/compiler.js +102 -0
  55. package/dist/engine/template/field-accessor.js +25 -0
  56. package/dist/engine/template/filters.js +94 -0
  57. package/dist/engine/template/index.js +5 -0
  58. package/dist/engine/template/parser.js +190 -0
  59. package/dist/engine/template/tokenizer.js +96 -0
  60. package/dist/engine/template/types.js +2 -0
  61. package/dist/types.js +2 -1
  62. package/dist/ui/display-adapter.js +60 -0
  63. package/dist/ui/earthquake-formatter.js +17 -5
  64. package/dist/ui/eew-formatter.js +25 -10
  65. package/dist/ui/formatter.js +67 -32
  66. package/dist/ui/minimap/grid-layout.js +91 -0
  67. package/dist/ui/minimap/index.js +16 -0
  68. package/dist/ui/minimap/minimap-renderer.js +277 -0
  69. package/dist/ui/minimap/pref-mapping.js +82 -0
  70. package/dist/ui/minimap/types.js +2 -0
  71. package/dist/ui/night-overlay.js +56 -0
  72. package/dist/ui/repl-handlers/command-definitions.js +320 -0
  73. package/dist/ui/repl-handlers/index.js +11 -0
  74. package/dist/ui/repl-handlers/info-handlers.js +577 -0
  75. package/dist/ui/repl-handlers/operation-handlers.js +233 -0
  76. package/dist/ui/repl-handlers/settings-handlers.js +923 -0
  77. package/dist/ui/repl-handlers/types.js +10 -0
  78. package/dist/ui/repl.js +81 -1752
  79. package/dist/ui/statistics-formatter.js +208 -0
  80. package/dist/ui/status-line.js +69 -0
  81. package/dist/ui/summary/index.js +5 -0
  82. package/dist/ui/summary/summary-line.js +18 -0
  83. package/dist/ui/summary/summary-model.js +31 -0
  84. package/dist/ui/summary/token-builders.js +317 -0
  85. package/dist/ui/summary/types.js +2 -0
  86. package/dist/ui/summary/width-fit.js +41 -0
  87. package/dist/ui/summary-interval-formatter.js +72 -0
  88. package/dist/ui/theme.js +34 -5
  89. package/dist/ui/tip-shuffler.js +81 -0
  90. package/dist/ui/volcano-formatter.js +15 -13
  91. package/dist/ui/waiting-tips.js +289 -249
  92. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromEarthquakeOutcome = fromEarthquakeOutcome;
4
+ const intensity_1 = require("../../../utils/intensity");
5
+ /** EarthquakeOutcome → PresentationEvent */
6
+ function fromEarthquakeOutcome(outcome) {
7
+ const xmlReport = outcome.msg.xmlReport;
8
+ const info = outcome.parsed;
9
+ const maxInt = info.intensity?.maxInt ?? null;
10
+ const maxIntRank = maxInt != null ? (0, intensity_1.intensityToRank)(maxInt) : null;
11
+ const areas = info.intensity?.areas ?? [];
12
+ const areaNames = areas.map((a) => a.name);
13
+ const areaItems = areas.map((a) => ({
14
+ name: a.name,
15
+ maxInt: a.intensity,
16
+ }));
17
+ return {
18
+ id: outcome.msg.id,
19
+ classification: outcome.msg.classification,
20
+ domain: outcome.domain,
21
+ type: outcome.headType,
22
+ infoType: xmlReport?.head.infoType ?? "不明",
23
+ title: xmlReport?.head.title ?? outcome.headType,
24
+ headline: xmlReport?.head.headline ?? null,
25
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
26
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
27
+ isTest: outcome.msg.head.test,
28
+ frameLevel: outcome.presentation.frameLevel,
29
+ soundLevel: outcome.presentation.soundLevel,
30
+ notifyCategory: outcome.presentation.notifyCategory,
31
+ isCancellation: info.infoType === "取消",
32
+ eventId: xmlReport?.head.eventId ?? null,
33
+ serial: xmlReport?.head.serial ?? null,
34
+ originTime: info.earthquake?.originTime ?? null,
35
+ hypocenterName: info.earthquake?.hypocenterName ?? null,
36
+ latitude: info.earthquake?.latitude ?? null,
37
+ longitude: info.earthquake?.longitude ?? null,
38
+ depth: info.earthquake?.depth ?? null,
39
+ magnitude: info.earthquake?.magnitude ?? null,
40
+ maxInt,
41
+ maxIntRank,
42
+ areaNames,
43
+ forecastAreaNames: [],
44
+ municipalityNames: [],
45
+ observationNames: [],
46
+ areaCount: areaNames.length,
47
+ forecastAreaCount: 0,
48
+ municipalityCount: 0,
49
+ observationCount: 0,
50
+ areaItems,
51
+ raw: outcome.parsed,
52
+ };
53
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromEewOutcome = fromEewOutcome;
4
+ const intensity_1 = require("../../../utils/intensity");
5
+ /** EewOutcome → PresentationEvent */
6
+ function fromEewOutcome(outcome) {
7
+ const xmlReport = outcome.msg.xmlReport;
8
+ const info = outcome.parsed;
9
+ // 予測地域から最大予測震度を算出
10
+ const forecastAreas = info.forecastIntensity?.areas ?? [];
11
+ let forecastMaxInt = null;
12
+ let forecastMaxIntRank = null;
13
+ for (const area of forecastAreas) {
14
+ const rank = (0, intensity_1.intensityToRank)(area.intensity);
15
+ if (forecastMaxIntRank == null || rank > forecastMaxIntRank) {
16
+ forecastMaxIntRank = rank;
17
+ forecastMaxInt = area.intensity;
18
+ }
19
+ }
20
+ const areaNames = forecastAreas.map((a) => a.name);
21
+ const areaItems = forecastAreas.map((a) => ({
22
+ name: a.name,
23
+ kind: "forecast",
24
+ maxInt: a.intensity,
25
+ }));
26
+ return {
27
+ id: outcome.msg.id,
28
+ classification: outcome.msg.classification,
29
+ domain: outcome.domain,
30
+ type: outcome.headType,
31
+ infoType: xmlReport?.head.infoType ?? "不明",
32
+ title: xmlReport?.head.title ?? outcome.headType,
33
+ headline: xmlReport?.head.headline ?? null,
34
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
35
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
36
+ isTest: outcome.msg.head.test,
37
+ frameLevel: outcome.presentation.frameLevel,
38
+ soundLevel: outcome.presentation.soundLevel,
39
+ notifyCategory: outcome.presentation.notifyCategory,
40
+ isCancellation: info.infoType === "取消",
41
+ eventId: info.eventId ?? xmlReport?.head.eventId ?? null,
42
+ serial: info.serial ?? xmlReport?.head.serial ?? null,
43
+ isWarning: info.isWarning,
44
+ isFinal: info.nextAdvisory != null,
45
+ isAssumedHypocenter: info.isAssumedHypocenter,
46
+ hypocenterName: info.earthquake?.hypocenterName ?? null,
47
+ latitude: info.earthquake?.latitude ?? null,
48
+ longitude: info.earthquake?.longitude ?? null,
49
+ depth: info.earthquake?.depth ?? null,
50
+ magnitude: info.earthquake?.magnitude ?? null,
51
+ forecastMaxInt: forecastMaxInt,
52
+ forecastMaxIntRank: forecastMaxIntRank,
53
+ nextAdvisory: info.nextAdvisory ?? null,
54
+ areaNames,
55
+ forecastAreaNames: areaNames,
56
+ municipalityNames: [],
57
+ observationNames: [],
58
+ areaCount: areaNames.length,
59
+ forecastAreaCount: areaNames.length,
60
+ municipalityCount: 0,
61
+ observationCount: 0,
62
+ areaItems,
63
+ stateSnapshot: {
64
+ kind: "eew",
65
+ activeCount: outcome.state.activeCount,
66
+ colorIndex: outcome.state.colorIndex,
67
+ isCancelled: outcome.state.isCancelled,
68
+ diff: outcome.state.diff,
69
+ },
70
+ raw: outcome.parsed,
71
+ };
72
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromLgObservationOutcome = fromLgObservationOutcome;
4
+ const intensity_1 = require("../../../utils/intensity");
5
+ /** LgObservationOutcome → PresentationEvent */
6
+ function fromLgObservationOutcome(outcome) {
7
+ const xmlReport = outcome.msg.xmlReport;
8
+ const info = outcome.parsed;
9
+ const maxLgInt = info.maxLgInt ?? null;
10
+ const maxLgIntRank = maxLgInt != null ? Number(maxLgInt) || null : null;
11
+ const observations = info.areas ?? [];
12
+ const observationNames = observations.map((o) => o.name);
13
+ const areaItems = observations.map((o) => ({
14
+ name: o.name,
15
+ maxInt: o.maxInt,
16
+ maxLgInt: o.maxLgInt,
17
+ }));
18
+ const maxInt = info.maxInt ?? null;
19
+ const maxIntRank = maxInt != null ? (0, intensity_1.intensityToRank)(maxInt) : null;
20
+ return {
21
+ id: outcome.msg.id,
22
+ classification: outcome.msg.classification,
23
+ domain: outcome.domain,
24
+ type: outcome.headType,
25
+ infoType: xmlReport?.head.infoType ?? "不明",
26
+ title: xmlReport?.head.title ?? outcome.headType,
27
+ headline: xmlReport?.head.headline ?? null,
28
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
29
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
30
+ isTest: outcome.msg.head.test,
31
+ frameLevel: outcome.presentation.frameLevel,
32
+ soundLevel: outcome.presentation.soundLevel,
33
+ notifyCategory: outcome.presentation.notifyCategory,
34
+ isCancellation: info.infoType === "取消",
35
+ eventId: xmlReport?.head.eventId ?? null,
36
+ serial: xmlReport?.head.serial ?? null,
37
+ originTime: info.earthquake?.originTime ?? null,
38
+ hypocenterName: info.earthquake?.hypocenterName ?? null,
39
+ latitude: info.earthquake?.latitude ?? null,
40
+ longitude: info.earthquake?.longitude ?? null,
41
+ depth: info.earthquake?.depth ?? null,
42
+ magnitude: info.earthquake?.magnitude ?? null,
43
+ maxInt,
44
+ maxIntRank,
45
+ maxLgInt,
46
+ maxLgIntRank,
47
+ areaNames: [],
48
+ forecastAreaNames: [],
49
+ municipalityNames: [],
50
+ observationNames,
51
+ areaCount: 0,
52
+ forecastAreaCount: 0,
53
+ municipalityCount: 0,
54
+ observationCount: observationNames.length,
55
+ areaItems,
56
+ raw: outcome.parsed,
57
+ };
58
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromNankaiTroughOutcome = fromNankaiTroughOutcome;
4
+ /** NankaiTroughOutcome → PresentationEvent */
5
+ function fromNankaiTroughOutcome(outcome) {
6
+ const xmlReport = outcome.msg.xmlReport;
7
+ const info = outcome.parsed;
8
+ return {
9
+ id: outcome.msg.id,
10
+ classification: outcome.msg.classification,
11
+ domain: outcome.domain,
12
+ type: outcome.headType,
13
+ infoType: xmlReport?.head.infoType ?? "不明",
14
+ title: xmlReport?.head.title ?? outcome.headType,
15
+ headline: xmlReport?.head.headline ?? null,
16
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
17
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
18
+ isTest: outcome.msg.head.test,
19
+ frameLevel: outcome.presentation.frameLevel,
20
+ soundLevel: outcome.presentation.soundLevel,
21
+ notifyCategory: outcome.presentation.notifyCategory,
22
+ isCancellation: info.infoType === "取消",
23
+ eventId: xmlReport?.head.eventId ?? null,
24
+ serial: xmlReport?.head.serial ?? null,
25
+ infoSerialCode: info.infoSerial?.code ?? null,
26
+ bodyText: info.bodyText,
27
+ nextAdvisory: info.nextAdvisory ?? null,
28
+ areaNames: [],
29
+ forecastAreaNames: [],
30
+ municipalityNames: [],
31
+ observationNames: [],
32
+ areaCount: 0,
33
+ forecastAreaCount: 0,
34
+ municipalityCount: 0,
35
+ observationCount: 0,
36
+ areaItems: [],
37
+ raw: outcome.parsed,
38
+ };
39
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromRawOutcome = fromRawOutcome;
4
+ /** RawOutcome → PresentationEvent (フォールバック用の最小変換) */
5
+ function fromRawOutcome(outcome) {
6
+ const xmlReport = outcome.msg.xmlReport;
7
+ return {
8
+ id: outcome.msg.id,
9
+ classification: outcome.msg.classification,
10
+ domain: outcome.domain,
11
+ type: outcome.headType,
12
+ infoType: xmlReport?.head.infoType ?? "不明",
13
+ title: xmlReport?.head.title ?? outcome.headType,
14
+ headline: xmlReport?.head.headline ?? null,
15
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
16
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
17
+ isTest: outcome.msg.head.test,
18
+ frameLevel: outcome.presentation.frameLevel,
19
+ soundLevel: outcome.presentation.soundLevel,
20
+ notifyCategory: outcome.presentation.notifyCategory,
21
+ isCancellation: false,
22
+ eventId: xmlReport?.head.eventId ?? null,
23
+ serial: xmlReport?.head.serial ?? null,
24
+ areaNames: [],
25
+ forecastAreaNames: [],
26
+ municipalityNames: [],
27
+ observationNames: [],
28
+ areaCount: 0,
29
+ forecastAreaCount: 0,
30
+ municipalityCount: 0,
31
+ observationCount: 0,
32
+ areaItems: [],
33
+ raw: null,
34
+ };
35
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromSeismicTextOutcome = fromSeismicTextOutcome;
4
+ /** SeismicTextOutcome → PresentationEvent */
5
+ function fromSeismicTextOutcome(outcome) {
6
+ const xmlReport = outcome.msg.xmlReport;
7
+ const info = outcome.parsed;
8
+ return {
9
+ id: outcome.msg.id,
10
+ classification: outcome.msg.classification,
11
+ domain: outcome.domain,
12
+ type: outcome.headType,
13
+ infoType: xmlReport?.head.infoType ?? "不明",
14
+ title: xmlReport?.head.title ?? outcome.headType,
15
+ headline: xmlReport?.head.headline ?? null,
16
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
17
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
18
+ isTest: outcome.msg.head.test,
19
+ frameLevel: outcome.presentation.frameLevel,
20
+ soundLevel: outcome.presentation.soundLevel,
21
+ notifyCategory: outcome.presentation.notifyCategory,
22
+ isCancellation: info.infoType === "取消",
23
+ eventId: xmlReport?.head.eventId ?? null,
24
+ serial: xmlReport?.head.serial ?? null,
25
+ bodyText: info.bodyText,
26
+ areaNames: [],
27
+ forecastAreaNames: [],
28
+ municipalityNames: [],
29
+ observationNames: [],
30
+ areaCount: 0,
31
+ forecastAreaCount: 0,
32
+ municipalityCount: 0,
33
+ observationCount: 0,
34
+ areaItems: [],
35
+ raw: outcome.parsed,
36
+ };
37
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromTsunamiOutcome = fromTsunamiOutcome;
4
+ /** TsunamiOutcome → PresentationEvent */
5
+ function fromTsunamiOutcome(outcome) {
6
+ const xmlReport = outcome.msg.xmlReport;
7
+ const info = outcome.parsed;
8
+ const forecastItems = info.forecast ?? [];
9
+ const forecastAreaNames = forecastItems.map((f) => f.areaName);
10
+ const tsunamiKinds = forecastItems.map((f) => f.kind);
11
+ const areaItems = forecastItems.map((f) => ({
12
+ name: f.areaName,
13
+ kind: f.kind,
14
+ }));
15
+ return {
16
+ id: outcome.msg.id,
17
+ classification: outcome.msg.classification,
18
+ domain: outcome.domain,
19
+ type: outcome.headType,
20
+ infoType: xmlReport?.head.infoType ?? "不明",
21
+ title: xmlReport?.head.title ?? outcome.headType,
22
+ headline: xmlReport?.head.headline ?? null,
23
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
24
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
25
+ isTest: outcome.msg.head.test,
26
+ frameLevel: outcome.presentation.frameLevel,
27
+ soundLevel: outcome.presentation.soundLevel,
28
+ notifyCategory: outcome.presentation.notifyCategory,
29
+ isCancellation: info.infoType === "取消",
30
+ eventId: xmlReport?.head.eventId ?? null,
31
+ serial: xmlReport?.head.serial ?? null,
32
+ warningComment: info.warningComment || null,
33
+ tsunamiKinds,
34
+ areaNames: [],
35
+ forecastAreaNames,
36
+ municipalityNames: [],
37
+ observationNames: [],
38
+ areaCount: 0,
39
+ forecastAreaCount: forecastAreaNames.length,
40
+ municipalityCount: 0,
41
+ observationCount: 0,
42
+ areaItems,
43
+ stateSnapshot: {
44
+ kind: "tsunami",
45
+ levelBefore: outcome.state.levelBefore,
46
+ levelAfter: outcome.state.levelAfter,
47
+ changed: outcome.state.changed,
48
+ },
49
+ raw: outcome.parsed,
50
+ };
51
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromVolcanoOutcome = fromVolcanoOutcome;
4
+ /** VolcanoOutcome | VolcanoBatchOutcome → PresentationEvent */
5
+ function fromVolcanoOutcome(outcome) {
6
+ if ("isBatch" in outcome && outcome.isBatch) {
7
+ return fromVolcanoBatchOutcome(outcome);
8
+ }
9
+ return fromSingleVolcanoOutcome(outcome);
10
+ }
11
+ function fromSingleVolcanoOutcome(outcome) {
12
+ const xmlReport = outcome.msg.xmlReport;
13
+ const info = outcome.parsed;
14
+ const alertLevel = info.kind === "alert" ? info.alertLevel : null;
15
+ return {
16
+ id: outcome.msg.id,
17
+ classification: outcome.msg.classification,
18
+ domain: outcome.domain,
19
+ type: outcome.headType,
20
+ infoType: xmlReport?.head.infoType ?? "不明",
21
+ title: xmlReport?.head.title ?? outcome.headType,
22
+ headline: xmlReport?.head.headline ?? null,
23
+ reportDateTime: xmlReport?.head.reportDateTime ?? outcome.msg.head.time,
24
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
25
+ isTest: outcome.msg.head.test,
26
+ frameLevel: outcome.presentation.frameLevel,
27
+ soundLevel: outcome.presentation.soundLevel,
28
+ notifyCategory: outcome.presentation.notifyCategory,
29
+ isCancellation: info.infoType === "取消",
30
+ isRenotification: outcome.state.isRenotification,
31
+ eventId: xmlReport?.head.eventId ?? null,
32
+ serial: xmlReport?.head.serial ?? null,
33
+ volcanoCode: info.volcanoCode,
34
+ volcanoName: info.volcanoName,
35
+ alertLevel,
36
+ areaNames: [],
37
+ forecastAreaNames: [],
38
+ municipalityNames: [],
39
+ observationNames: [],
40
+ areaCount: 0,
41
+ forecastAreaCount: 0,
42
+ municipalityCount: 0,
43
+ observationCount: 0,
44
+ areaItems: [],
45
+ stateSnapshot: {
46
+ kind: "volcano",
47
+ isRenotification: outcome.state.isRenotification,
48
+ },
49
+ raw: outcome.parsed,
50
+ };
51
+ }
52
+ function fromVolcanoBatchOutcome(outcome) {
53
+ const xmlReport = outcome.msg.xmlReport;
54
+ const firstItem = outcome.parsed[0];
55
+ const volcanoName = firstItem?.volcanoName ?? null;
56
+ const volcanoCode = firstItem?.volcanoCode ?? null;
57
+ return {
58
+ id: outcome.msg.id,
59
+ classification: outcome.msg.classification,
60
+ domain: outcome.domain,
61
+ type: outcome.headType,
62
+ subType: "ashfallBatch",
63
+ infoType: xmlReport?.head.infoType ?? "不明",
64
+ title: xmlReport?.head.title ?? outcome.headType,
65
+ headline: xmlReport?.head.headline ?? null,
66
+ reportDateTime: outcome.batchReportDateTime,
67
+ publishingOffice: xmlReport?.control.publishingOffice ?? outcome.msg.head.author,
68
+ isTest: outcome.batchIsTest,
69
+ frameLevel: outcome.presentation.frameLevel,
70
+ soundLevel: outcome.presentation.soundLevel,
71
+ notifyCategory: outcome.presentation.notifyCategory,
72
+ isCancellation: false,
73
+ eventId: xmlReport?.head.eventId ?? null,
74
+ serial: xmlReport?.head.serial ?? null,
75
+ volcanoCode,
76
+ volcanoName,
77
+ areaNames: [],
78
+ forecastAreaNames: [],
79
+ municipalityNames: [],
80
+ observationNames: [],
81
+ areaCount: 0,
82
+ forecastAreaCount: 0,
83
+ municipalityCount: 0,
84
+ observationCount: 0,
85
+ areaItems: [],
86
+ raw: outcome.parsed,
87
+ };
88
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toPresentationEvent = toPresentationEvent;
4
+ const from_eew_1 = require("./from-eew");
5
+ const from_earthquake_1 = require("./from-earthquake");
6
+ const from_seismic_text_1 = require("./from-seismic-text");
7
+ const from_lg_observation_1 = require("./from-lg-observation");
8
+ const from_tsunami_1 = require("./from-tsunami");
9
+ const from_volcano_1 = require("./from-volcano");
10
+ const from_nankai_trough_1 = require("./from-nankai-trough");
11
+ const from_raw_1 = require("./from-raw");
12
+ /** ProcessOutcome → PresentationEvent に変換する */
13
+ function toPresentationEvent(outcome) {
14
+ switch (outcome.domain) {
15
+ case "eew":
16
+ return (0, from_eew_1.fromEewOutcome)(outcome);
17
+ case "earthquake":
18
+ return (0, from_earthquake_1.fromEarthquakeOutcome)(outcome);
19
+ case "seismicText":
20
+ return (0, from_seismic_text_1.fromSeismicTextOutcome)(outcome);
21
+ case "lgObservation":
22
+ return (0, from_lg_observation_1.fromLgObservationOutcome)(outcome);
23
+ case "tsunami":
24
+ return (0, from_tsunami_1.fromTsunamiOutcome)(outcome);
25
+ case "volcano":
26
+ return (0, from_volcano_1.fromVolcanoOutcome)(outcome);
27
+ case "nankaiTrough":
28
+ return (0, from_nankai_trough_1.fromNankaiTroughOutcome)(outcome);
29
+ case "raw":
30
+ return (0, from_raw_1.fromRawOutcome)(outcome);
31
+ }
32
+ }
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.eewFrameLevel = eewFrameLevel;
4
+ exports.earthquakeFrameLevel = earthquakeFrameLevel;
5
+ exports.tsunamiFrameLevel = tsunamiFrameLevel;
6
+ exports.seismicTextFrameLevel = seismicTextFrameLevel;
7
+ exports.nankaiTroughFrameLevel = nankaiTroughFrameLevel;
8
+ exports.lgObservationFrameLevel = lgObservationFrameLevel;
9
+ exports.eewSoundLevel = eewSoundLevel;
10
+ exports.earthquakeSoundLevel = earthquakeSoundLevel;
11
+ exports.tsunamiSoundLevel = tsunamiSoundLevel;
12
+ exports.seismicTextSoundLevel = seismicTextSoundLevel;
13
+ exports.nankaiTroughSoundLevel = nankaiTroughSoundLevel;
14
+ exports.lgObservationSoundLevel = lgObservationSoundLevel;
15
+ const intensity_1 = require("../../utils/intensity");
16
+ // ── frameLevel ──
17
+ function eewFrameLevel(info) {
18
+ if (info.infoType === "取消")
19
+ return "cancel";
20
+ if (info.isWarning)
21
+ return "critical";
22
+ return "warning";
23
+ }
24
+ function earthquakeFrameLevel(info) {
25
+ if (info.infoType === "取消")
26
+ return "cancel";
27
+ if (info.intensity) {
28
+ const rank = (0, intensity_1.intensityToRank)(info.intensity.maxInt);
29
+ if (rank >= 7)
30
+ return "critical";
31
+ if (rank >= 4)
32
+ return "warning";
33
+ }
34
+ return "normal";
35
+ }
36
+ function tsunamiFrameLevel(info) {
37
+ if (info.infoType === "取消")
38
+ return "cancel";
39
+ const kinds = (info.forecast || []).map((f) => f.kind);
40
+ if (kinds.some((kind) => kind.includes("大津波警報")))
41
+ return "critical";
42
+ if (kinds.some((kind) => kind.includes("津波警報")))
43
+ return "warning";
44
+ return "normal";
45
+ }
46
+ function seismicTextFrameLevel(info) {
47
+ return info.infoType === "取消" ? "cancel" : "info";
48
+ }
49
+ function nankaiTroughFrameLevel(info) {
50
+ if (info.infoType === "取消")
51
+ return "cancel";
52
+ if (!info.infoSerial)
53
+ return "warning";
54
+ const code = info.infoSerial.code;
55
+ if (code === "120")
56
+ return "critical";
57
+ if (code === "130")
58
+ return "warning";
59
+ if (code === "111" || code === "112" || code === "113")
60
+ return "warning";
61
+ if (code === "210" || code === "219")
62
+ return "warning";
63
+ if (code === "190" || code === "200")
64
+ return "info";
65
+ return "warning";
66
+ }
67
+ function lgObservationFrameLevel(info) {
68
+ if (info.infoType === "取消")
69
+ return "cancel";
70
+ if (info.maxLgInt) {
71
+ const num = Number(info.maxLgInt);
72
+ if (!Number.isNaN(num)) {
73
+ if (num >= 4)
74
+ return "critical";
75
+ if (num >= 3)
76
+ return "warning";
77
+ if (num >= 2)
78
+ return "normal";
79
+ }
80
+ }
81
+ return "info";
82
+ }
83
+ // ── soundLevel ──
84
+ function eewSoundLevel(info) {
85
+ return info.isWarning ? "critical" : "warning";
86
+ }
87
+ function earthquakeSoundLevel(info) {
88
+ if (!info.intensity)
89
+ return "normal";
90
+ if ((0, intensity_1.intensityToRank)(info.intensity.maxInt) >= 4)
91
+ return "warning";
92
+ return "normal";
93
+ }
94
+ function tsunamiSoundLevel(info) {
95
+ if (!info.forecast || info.forecast.length === 0)
96
+ return "normal";
97
+ const kinds = info.forecast.map((f) => f.kind);
98
+ if (kinds.some((k) => k.includes("津波") && !k.includes("解除")))
99
+ return "critical";
100
+ if (kinds.some((k) => k.includes("解除")))
101
+ return "warning";
102
+ return "normal";
103
+ }
104
+ function seismicTextSoundLevel(_info) {
105
+ return "info";
106
+ }
107
+ function nankaiTroughSoundLevel(info) {
108
+ return info.infoSerial?.code === "120" ? "critical" : "warning";
109
+ }
110
+ function lgObservationSoundLevel(info) {
111
+ if (!info.maxLgInt)
112
+ return "normal";
113
+ if (info.maxLgInt === "4" || info.maxLgInt === "3")
114
+ return "critical";
115
+ if (info.maxLgInt === "2" || info.maxLgInt === "1")
116
+ return "warning";
117
+ return "normal";
118
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processEarthquake = processEarthquake;
4
+ const telegram_parser_1 = require("../../../dmdata/telegram-parser");
5
+ const level_helpers_1 = require("../level-helpers");
6
+ /**
7
+ * 地震電文 (VXSE51/52/53/61) を処理し EarthquakeOutcome を返す。
8
+ * パース失敗の場合は null を返す。
9
+ */
10
+ function processEarthquake(msg) {
11
+ const eqInfo = (0, telegram_parser_1.parseEarthquakeTelegram)(msg);
12
+ if (!eqInfo)
13
+ return null;
14
+ const eventId = msg.xmlReport?.head.eventId ?? null;
15
+ const maxIntUpdate = eventId && eqInfo.intensity?.maxInt
16
+ ? { eventId, maxInt: eqInfo.intensity.maxInt, headType: msg.head.type }
17
+ : undefined;
18
+ return {
19
+ domain: "earthquake",
20
+ msg,
21
+ headType: msg.head.type,
22
+ statsCategory: "earthquake",
23
+ parsed: eqInfo,
24
+ state: eventId ? { eventId, representativeMaxInt: eqInfo.intensity?.maxInt } : undefined,
25
+ stats: {
26
+ shouldRecord: true,
27
+ eventId,
28
+ maxIntUpdate,
29
+ },
30
+ presentation: {
31
+ frameLevel: (0, level_helpers_1.earthquakeFrameLevel)(eqInfo),
32
+ soundLevel: (0, level_helpers_1.earthquakeSoundLevel)(eqInfo),
33
+ notifyCategory: "earthquake",
34
+ },
35
+ };
36
+ }