fix: resolve merge conflicts between JSDF bases and East Asia adversary bases

Merge both feature sets: keep JSDF bases (gsdf/msdf/asdf branches) from
PR #77 and East Asia adversary bases (missile/nuclear branches) from main.
Union all branch types in tests and MaplibreViewer labels.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
adust09
2026-03-17 01:10:19 +09:00
14 changed files with 1466 additions and 11 deletions
+14 -6
View File
@@ -1475,11 +1475,11 @@ const MaplibreViewer = ({ data, activeLayers, onEntityClick, flyToLocation, sele
id="military-bases-layer"
type="circle"
paint={{
'circle-color': '#ef4444',
'circle-color': ['match', ['get', 'side'], 'red', '#ef4444', 'green', '#22c55e', '#3b82f6'],
'circle-radius': ['interpolate', ['linear'], ['zoom'], 2, 4, 6, 7, 10, 10],
'circle-opacity': 0.8,
'circle-stroke-width': 2,
'circle-stroke-color': '#fca5a5',
'circle-stroke-color': ['match', ['get', 'side'], 'red', '#fca5a5', 'green', '#86efac', '#93c5fd'],
}}
/>
<Layer
@@ -1494,7 +1494,7 @@ const MaplibreViewer = ({ data, activeLayers, onEntityClick, flyToLocation, sele
'text-allow-overlap': false,
}}
paint={{
'text-color': '#fca5a5',
'text-color': ['match', ['get', 'side'], 'red', '#fca5a5', 'green', '#86efac', '#93c5fd'],
'text-halo-color': 'rgba(0,0,0,0.9)',
'text-halo-width': 1,
}}
@@ -1891,7 +1891,15 @@ const MaplibreViewer = ({ data, activeLayers, onEntityClick, flyToLocation, sele
const branchLabel: Record<string, string> = {
air_force: 'AIR FORCE', navy: 'NAVY', marines: 'MARINES', army: 'ARMY',
gsdf: 'GSDF (陸自)', msdf: 'MSDF (海自)', asdf: 'ASDF (空自)',
missile: 'MISSILE FORCES', nuclear: 'NUCLEAR FACILITY',
};
const isAdversary = ['China', 'Russia', 'North Korea'].includes(base.country);
const isROC = base.country === 'Taiwan';
const accentColor = isAdversary ? 'red' : isROC ? 'green' : 'blue';
const borderCls = isAdversary ? 'border-red-400/40' : isROC ? 'border-green-400/40' : 'border-blue-400/40';
const textCls = isAdversary ? 'text-[#fca5a5]' : isROC ? 'text-[#86efac]' : 'text-[#93c5fd]';
const titleCls = isAdversary ? 'text-red-400 border-b border-red-400/20' : isROC ? 'text-green-400 border-b border-green-400/20' : 'text-blue-400 border-b border-blue-400/20';
const footerCls = isAdversary ? 'text-red-600' : isROC ? 'text-green-600' : 'text-blue-600';
return (
<Popup
longitude={base.lng}
@@ -1902,8 +1910,8 @@ const MaplibreViewer = ({ data, activeLayers, onEntityClick, flyToLocation, sele
className="threat-popup"
maxWidth="280px"
>
<div className="map-popup bg-[#1a1035] border border-red-400/40 text-[#fca5a5] min-w-[200px]">
<div className="map-popup-title text-red-400 border-b border-red-400/20 pb-1">
<div className={`map-popup bg-[#1a1035] border ${borderCls} ${textCls} min-w-[200px]`}>
<div className={`map-popup-title ${titleCls} pb-1`}>
{base.name}
</div>
<div className="map-popup-row">
@@ -1912,7 +1920,7 @@ const MaplibreViewer = ({ data, activeLayers, onEntityClick, flyToLocation, sele
<div className="map-popup-row">
Location: <span className="text-white">{base.country}</span>
</div>
<div className="mt-1.5 text-[9px] text-red-600 tracking-wider">
<div className={`mt-1.5 text-[9px] ${footerCls} tracking-wider`}>
MILITARY BASE {branchLabel[base.branch] || base.branch.toUpperCase()}
</div>
</div>
@@ -197,6 +197,16 @@ export function buildDataCentersGeoJSON(datacenters?: DataCenter[]): FC {
// ─── Military Bases ─────────────────────────────────────────────────────────
// Classify base alignment: red = adversary, blue = US/allied, green = ROC
const _ADVERSARY_COUNTRIES = new Set(["China", "Russia", "North Korea"]);
const _ROC_COUNTRIES = new Set(["Taiwan"]);
function _baseSide(country: string, operator: string): "red" | "blue" | "green" {
if (_ADVERSARY_COUNTRIES.has(country)) return "red";
if (_ROC_COUNTRIES.has(country)) return "green";
return "blue";
}
export function buildMilitaryBasesGeoJSON(bases?: MilitaryBase[]): FC {
if (!bases?.length) return null;
return {
@@ -210,6 +220,7 @@ export function buildMilitaryBasesGeoJSON(bases?: MilitaryBase[]): FC {
country: base.country || '',
operator: base.operator || '',
branch: base.branch || '',
side: _baseSide(base.country || '', base.operator || ''),
},
geometry: { type: 'Point' as const, coordinates: [base.lng, base.lat] }
}))