From 7d6d9a14363487e3a15a5200616a2903965c9b9c Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Jan 2026 23:00:35 +0000 Subject: [PATCH 1/2] Add comprehensive infrastructure database with JSON loader New data/infrastructure.json contains 23 assets: - 12 submarine cables (C-Lion1, Estlink 1/2, NordBalt, SwePol, etc.) - 4 gas pipelines (Balticconnector, Nord Stream 1/2, Europipe II) - 7 offshore wind farms (Kriegers Flak, Anholt, Arkona, etc.) Features: - JSON format for easy editing and expansion - Source attribution (TeleGeography, EMODnet, HELCOM) - Incident history tracking - Landing points with country codes - Protection radius and operator info Updated infra_analysis.py: - New load_infrastructure_from_json() function - get_all_infrastructure() loads JSON with fallback to hardcoded - Backwards compatible with existing code --- data/infrastructure.json | 570 +++++++++++++++++++++++++++++++++++++++ infra_analysis.py | 122 ++++++++- 2 files changed, 689 insertions(+), 3 deletions(-) create mode 100644 data/infrastructure.json diff --git a/data/infrastructure.json b/data/infrastructure.json new file mode 100644 index 0000000..e37b645 --- /dev/null +++ b/data/infrastructure.json @@ -0,0 +1,570 @@ +{ + "metadata": { + "version": "1.0", + "last_updated": "2026-01-01", + "description": "Undersea infrastructure database for maritime monitoring", + "sources": [ + "TeleGeography Submarine Cable Map (submarinecablemap.com)", + "EMODnet Human Activities", + "HELCOM Baltic Sea data", + "Wikipedia infrastructure lists", + "Operator websites" + ] + }, + "regions": { + "baltic_sea": { + "name": "Baltic Sea", + "bounds": { + "min_lat": 53.0, + "max_lat": 66.0, + "min_lon": 9.0, + "max_lon": 30.0 + } + } + }, + "cables": [ + { + "id": "clion1", + "name": "C-Lion1", + "type": "telecom", + "subtype": "fiber_optic", + "status": "damaged", + "region": "baltic_sea", + "waypoints": [ + [60.17, 24.94], + [60.05, 24.80], + [59.70, 24.50], + [59.45, 23.50], + [58.80, 21.00], + [58.00, 18.50], + [56.50, 15.50], + [55.50, 13.50], + [54.50, 12.50], + [54.18, 12.09] + ], + "landing_points": [ + {"name": "Helsinki", "country": "FI", "lat": 60.17, "lon": 24.94}, + {"name": "Rostock", "country": "DE", "lat": 54.18, "lon": 12.09} + ], + "length_km": 1172, + "operator": "Cinia", + "capacity": "144 Tbps design capacity", + "rfs_year": 2016, + "protection_radius_nm": 5.0, + "notes": "Finland-Germany submarine telecom cable. Damaged Dec 31, 2025.", + "incidents": [ + {"date": "2025-12-31", "type": "damage", "description": "Cable damaged, under investigation"} + ] + }, + { + "id": "estlink2", + "name": "Estlink-2", + "type": "power", + "subtype": "hvdc", + "status": "damaged", + "region": "baltic_sea", + "waypoints": [ + [59.35, 27.75], + [59.45, 27.00], + [59.55, 26.20], + [59.70, 25.60], + [59.90, 25.30], + [60.10, 25.15] + ], + "landing_points": [ + {"name": "Purtse", "country": "EE", "lat": 59.35, "lon": 27.75}, + {"name": "Porvoo", "country": "FI", "lat": 60.10, "lon": 25.15} + ], + "length_km": 170, + "operator": "Elering/Fingrid", + "capacity": "650 MW", + "voltage_kv": 450, + "rfs_year": 2014, + "protection_radius_nm": 3.0, + "notes": "Estonia-Finland HVDC power interconnector. Damaged Dec 25, 2025 by Eagle S.", + "incidents": [ + {"date": "2025-12-25", "type": "damage", "vessel": "Eagle S", "description": "Anchor drag damage"} + ] + }, + { + "id": "estlink1", + "name": "Estlink-1", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [59.42, 24.52], + [59.50, 24.70], + [59.65, 24.90], + [59.85, 25.10], + [60.05, 25.35] + ], + "landing_points": [ + {"name": "Harku", "country": "EE", "lat": 59.42, "lon": 24.52}, + {"name": "Espoo", "country": "FI", "lat": 60.05, "lon": 25.35} + ], + "length_km": 105, + "operator": "Elering/Fingrid", + "capacity": "350 MW", + "voltage_kv": 150, + "rfs_year": 2006, + "protection_radius_nm": 3.0, + "notes": "First Estonia-Finland power interconnector." + }, + { + "id": "nordbalt", + "name": "NordBalt", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [55.52, 12.90], + [55.30, 13.50], + [55.20, 14.50], + [55.30, 15.50], + [55.50, 16.50], + [55.75, 17.50], + [55.92, 18.20] + ], + "landing_points": [ + {"name": "Klaipeda", "country": "LT", "lat": 55.92, "lon": 18.20}, + {"name": "Nybro", "country": "SE", "lat": 55.52, "lon": 12.90} + ], + "length_km": 450, + "operator": "Litgrid/Svenska Kraftnät", + "capacity": "700 MW", + "voltage_kv": 300, + "rfs_year": 2015, + "protection_radius_nm": 3.0, + "notes": "Lithuania-Sweden HVDC power interconnector." + }, + { + "id": "swepol", + "name": "SwePol Link", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [55.38, 12.85], + [55.20, 13.50], + [55.00, 14.50], + [54.70, 15.50], + [54.50, 16.50], + [54.40, 17.00], + [54.35, 18.67] + ], + "landing_points": [ + {"name": "Karlshamn", "country": "SE", "lat": 55.38, "lon": 12.85}, + {"name": "Slupsk", "country": "PL", "lat": 54.35, "lon": 18.67} + ], + "length_km": 245, + "operator": "Svenska Kraftnät/PSE", + "capacity": "600 MW", + "voltage_kv": 450, + "rfs_year": 2000, + "protection_radius_nm": 3.0, + "notes": "Sweden-Poland HVDC power interconnector." + }, + { + "id": "kontek", + "name": "Kontek", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [54.57, 11.25], + [54.55, 11.50], + [54.50, 11.80], + [54.45, 12.10], + [54.50, 12.30] + ], + "landing_points": [ + {"name": "Bentwisch", "country": "DE", "lat": 54.57, "lon": 11.25}, + {"name": "Bjaeverskov", "country": "DK", "lat": 54.50, "lon": 12.30} + ], + "length_km": 52, + "operator": "50Hertz/Energinet", + "capacity": "600 MW", + "voltage_kv": 400, + "rfs_year": 1995, + "protection_radius_nm": 2.0, + "notes": "Germany-Denmark power interconnector." + }, + { + "id": "baltickonnekt", + "name": "Baltic Cable", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [54.13, 12.12], + [54.50, 12.50], + [55.00, 12.80], + [55.40, 12.65] + ], + "landing_points": [ + {"name": "Lübeck-Herrenwyk", "country": "DE", "lat": 54.13, "lon": 12.12}, + {"name": "Trelleborg", "country": "SE", "lat": 55.40, "lon": 12.65} + ], + "length_km": 250, + "operator": "Baltic Cable AB", + "capacity": "600 MW", + "voltage_kv": 450, + "rfs_year": 1994, + "protection_radius_nm": 3.0, + "notes": "Germany-Sweden HVDC power interconnector." + }, + { + "id": "fennoskan1", + "name": "Fenno-Skan 1", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [60.45, 22.20], + [60.20, 20.50], + [59.80, 19.50], + [59.50, 18.80] + ], + "landing_points": [ + {"name": "Rauma", "country": "FI", "lat": 60.45, "lon": 22.20}, + {"name": "Dannebo", "country": "SE", "lat": 59.50, "lon": 18.80} + ], + "length_km": 200, + "operator": "Fingrid/Svenska Kraftnät", + "capacity": "500 MW", + "voltage_kv": 400, + "rfs_year": 1989, + "protection_radius_nm": 3.0, + "notes": "Finland-Sweden HVDC power interconnector." + }, + { + "id": "fennoskan2", + "name": "Fenno-Skan 2", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [60.45, 22.25], + [60.15, 20.40], + [59.75, 19.40], + [59.45, 18.75] + ], + "landing_points": [ + {"name": "Rauma", "country": "FI", "lat": 60.45, "lon": 22.25}, + {"name": "Finnböle", "country": "SE", "lat": 59.45, "lon": 18.75} + ], + "length_km": 200, + "operator": "Fingrid/Svenska Kraftnät", + "capacity": "800 MW", + "voltage_kv": 500, + "rfs_year": 2011, + "protection_radius_nm": 3.0, + "notes": "Second Finland-Sweden HVDC interconnector." + }, + { + "id": "gotlandlink", + "name": "Gotland HVDC Link", + "type": "power", + "subtype": "hvdc", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [57.65, 18.35], + [57.50, 17.80], + [57.40, 17.20], + [57.30, 16.70] + ], + "landing_points": [ + {"name": "Visby", "country": "SE", "lat": 57.65, "lon": 18.35}, + {"name": "Västervik", "country": "SE", "lat": 57.30, "lon": 16.70} + ], + "length_km": 96, + "operator": "Svenska Kraftnät", + "capacity": "130 MW", + "voltage_kv": 150, + "rfs_year": 1999, + "protection_radius_nm": 2.0, + "notes": "Mainland Sweden to Gotland island power link." + }, + { + "id": "aland_cable", + "name": "Åland Cable", + "type": "power", + "subtype": "ac", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [60.10, 19.95], + [60.05, 20.30], + [60.00, 20.80], + [59.95, 21.20] + ], + "landing_points": [ + {"name": "Mariehamn", "country": "AX", "lat": 60.10, "lon": 19.95}, + {"name": "Naantali", "country": "FI", "lat": 59.95, "lon": 21.20} + ], + "length_km": 80, + "operator": "Kraftnät Åland", + "capacity": "100 MW", + "rfs_year": 2015, + "protection_radius_nm": 2.0, + "notes": "Åland islands to Finland mainland." + }, + { + "id": "segw", + "name": "SE-GW (Scandinavian-German Offshore Wind)", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [55.60, 12.95], + [55.20, 13.40], + [54.70, 13.00], + [54.20, 12.50] + ], + "landing_points": [ + {"name": "Trelleborg", "country": "SE", "lat": 55.60, "lon": 12.95}, + {"name": "Sassnitz", "country": "DE", "lat": 54.20, "lon": 12.50} + ], + "length_km": 180, + "operator": "GlobalConnect", + "capacity": "Multi-Tbps", + "rfs_year": 2020, + "protection_radius_nm": 3.0, + "notes": "Sweden-Germany fiber cable via offshore wind farm area." + } + ], + "pipelines": [ + { + "id": "balticconnector", + "name": "Balticconnector", + "type": "gas", + "status": "damaged", + "region": "baltic_sea", + "waypoints": [ + [59.35, 24.05], + [59.50, 24.30], + [59.70, 24.60], + [59.90, 24.85], + [60.05, 25.00] + ], + "landing_points": [ + {"name": "Paldiski", "country": "EE", "lat": 59.35, "lon": 24.05}, + {"name": "Inkoo", "country": "FI", "lat": 60.05, "lon": 25.00} + ], + "length_km": 77, + "diameter_mm": 500, + "operator": "Gasgrid Finland/Elering", + "capacity": "7.2 bcm/year", + "rfs_year": 2019, + "protection_radius_nm": 5.0, + "notes": "Finland-Estonia bi-directional gas pipeline. Damaged Oct 2023 by anchor drag.", + "incidents": [ + {"date": "2023-10-08", "type": "damage", "vessel": "Newnew Polar Bear", "description": "Anchor drag damage"} + ] + }, + { + "id": "nordstream1", + "name": "Nord Stream 1", + "type": "gas", + "status": "destroyed", + "region": "baltic_sea", + "waypoints": [ + [59.95, 29.10], + [59.80, 27.00], + [59.60, 24.50], + [59.30, 21.00], + [58.50, 18.00], + [56.50, 14.50], + [55.00, 12.50], + [54.15, 12.10] + ], + "landing_points": [ + {"name": "Vyborg", "country": "RU", "lat": 59.95, "lon": 29.10}, + {"name": "Lubmin", "country": "DE", "lat": 54.15, "lon": 12.10} + ], + "length_km": 1224, + "diameter_mm": 1220, + "operator": "Nord Stream AG", + "capacity": "55 bcm/year", + "rfs_year": 2011, + "protection_radius_nm": 5.0, + "notes": "Russia-Germany gas pipeline. Destroyed by sabotage Sep 2022.", + "incidents": [ + {"date": "2022-09-26", "type": "sabotage", "description": "Multiple explosions, pipeline destroyed"} + ] + }, + { + "id": "nordstream2", + "name": "Nord Stream 2", + "type": "gas", + "status": "destroyed", + "region": "baltic_sea", + "waypoints": [ + [59.93, 29.15], + [59.75, 27.10], + [59.55, 24.60], + [59.25, 21.10], + [58.45, 18.10], + [56.45, 14.60], + [54.95, 12.55], + [54.12, 12.15] + ], + "landing_points": [ + {"name": "Ust-Luga", "country": "RU", "lat": 59.93, "lon": 29.15}, + {"name": "Lubmin", "country": "DE", "lat": 54.12, "lon": 12.15} + ], + "length_km": 1230, + "diameter_mm": 1220, + "operator": "Nord Stream 2 AG", + "capacity": "55 bcm/year", + "rfs_year": 2021, + "protection_radius_nm": 5.0, + "notes": "Never operated commercially. Destroyed by sabotage Sep 2022.", + "incidents": [ + {"date": "2022-09-26", "type": "sabotage", "description": "Multiple explosions, pipeline destroyed"} + ] + }, + { + "id": "europipe2", + "name": "Europipe II", + "type": "gas", + "status": "operational", + "region": "north_sea", + "waypoints": [ + [58.45, 1.75], + [57.00, 4.50], + [55.50, 6.50], + [54.00, 8.00], + [53.60, 8.55] + ], + "landing_points": [ + {"name": "Kårstø", "country": "NO", "lat": 58.45, "lon": 1.75}, + {"name": "Dornum", "country": "DE", "lat": 53.60, "lon": 8.55} + ], + "length_km": 658, + "diameter_mm": 1067, + "operator": "Gassco", + "capacity": "71 bcm/year", + "rfs_year": 1999, + "protection_radius_nm": 5.0, + "notes": "Norway-Germany gas pipeline." + } + ], + "wind_farms": [ + { + "id": "kriegers_flak", + "name": "Kriegers Flak", + "status": "operational", + "region": "baltic_sea", + "center": [55.15, 13.10], + "country": "DK", + "turbines": 72, + "capacity_mw": 605, + "operator": "Vattenfall", + "rfs_year": 2021, + "area_km2": 132, + "protection_radius_nm": 3.0, + "notes": "Combined Danish/German offshore wind farm in Baltic Sea." + }, + { + "id": "anholt", + "name": "Anholt Offshore Wind Farm", + "status": "operational", + "region": "baltic_sea", + "center": [56.60, 11.20], + "country": "DK", + "turbines": 111, + "capacity_mw": 400, + "operator": "Ørsted", + "rfs_year": 2013, + "area_km2": 88, + "protection_radius_nm": 2.0, + "notes": "Denmark's largest offshore wind farm in Kattegat." + }, + { + "id": "arkona", + "name": "Arkona Basin Southeast", + "status": "operational", + "region": "baltic_sea", + "center": [54.68, 14.10], + "country": "DE", + "turbines": 60, + "capacity_mw": 385, + "operator": "E.ON/Equinor", + "rfs_year": 2019, + "area_km2": 39, + "protection_radius_nm": 2.0, + "notes": "German offshore wind farm in Baltic Sea." + }, + { + "id": "wikinger", + "name": "Wikinger", + "status": "operational", + "region": "baltic_sea", + "center": [54.83, 14.07], + "country": "DE", + "turbines": 70, + "capacity_mw": 350, + "operator": "Iberdrola", + "rfs_year": 2017, + "area_km2": 34, + "protection_radius_nm": 2.0, + "notes": "German offshore wind farm northeast of Rügen." + }, + { + "id": "baltic2", + "name": "Baltic 2 (EnBW)", + "status": "operational", + "region": "baltic_sea", + "center": [54.98, 13.17], + "country": "DE", + "turbines": 80, + "capacity_mw": 288, + "operator": "EnBW", + "rfs_year": 2015, + "area_km2": 27, + "protection_radius_nm": 2.0, + "notes": "German offshore wind farm north of Rügen." + }, + { + "id": "lillgrund", + "name": "Lillgrund", + "status": "operational", + "region": "baltic_sea", + "center": [55.52, 12.77], + "country": "SE", + "turbines": 48, + "capacity_mw": 110, + "operator": "Vattenfall", + "rfs_year": 2007, + "area_km2": 18, + "protection_radius_nm": 1.5, + "notes": "Swedish offshore wind farm in Öresund strait." + }, + { + "id": "tahkoluoto", + "name": "Tahkoluoto", + "status": "operational", + "region": "baltic_sea", + "center": [61.63, 21.35], + "country": "FI", + "turbines": 10, + "capacity_mw": 42, + "operator": "Suomen Hyötytuuli", + "rfs_year": 2017, + "area_km2": 5, + "protection_radius_nm": 1.0, + "notes": "Finland's first offshore wind farm, ice-resistant design." + } + ] +} diff --git a/infra_analysis.py b/infra_analysis.py index 3f508f8..b089c57 100644 --- a/infra_analysis.py +++ b/infra_analysis.py @@ -34,6 +34,8 @@ from enum import Enum from typing import List, Dict, Optional, Tuple, Any import math +import json +import os from utils import haversine from behavior import ( @@ -41,6 +43,10 @@ analyze_vessel_behavior, BehaviorEvent ) +# Path to infrastructure data file +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +INFRASTRUCTURE_JSON_PATH = os.path.join(SCRIPT_DIR, 'data', 'infrastructure.json') + class InfrastructureType(Enum): """Types of undersea infrastructure.""" @@ -113,6 +119,116 @@ def get_nearest_point(self, lat: float, lon: float) -> Tuple[float, float, float return (0, 0, float('inf')) +# ============================================================================= +# Infrastructure Data Loading +# ============================================================================= + +def load_infrastructure_from_json(filepath: str = None) -> List['InfrastructureAsset']: + """ + Load infrastructure data from JSON file. + + Args: + filepath: Path to JSON file (defaults to data/infrastructure.json) + + Returns: + List of InfrastructureAsset objects + """ + if filepath is None: + filepath = INFRASTRUCTURE_JSON_PATH + + if not os.path.exists(filepath): + print(f"Infrastructure JSON not found at {filepath}, using fallback data") + return [] + + try: + with open(filepath, 'r') as f: + data = json.load(f) + except (json.JSONDecodeError, IOError) as e: + print(f"Error loading infrastructure JSON: {e}") + return [] + + assets = [] + + # Type mapping + type_map = { + 'telecom': InfrastructureType.TELECOM_CABLE, + 'fiber_optic': InfrastructureType.FIBER_OPTIC, + 'power': InfrastructureType.POWER_CABLE, + 'hvdc': InfrastructureType.POWER_CABLE, + 'ac': InfrastructureType.POWER_CABLE, + 'gas': InfrastructureType.GAS_PIPELINE, + 'oil': InfrastructureType.OIL_PIPELINE, + } + + # Load cables + for cable in data.get('cables', []): + infra_type = type_map.get(cable.get('type'), InfrastructureType.TELECOM_CABLE) + if cable.get('subtype') in type_map: + infra_type = type_map[cable.get('subtype')] + + waypoints = [tuple(wp) for wp in cable.get('waypoints', [])] + + assets.append(InfrastructureAsset( + name=cable.get('name', 'Unknown'), + infra_type=infra_type, + waypoints=waypoints, + protection_radius_nm=cable.get('protection_radius_nm', 3.0), + operator=cable.get('operator'), + capacity=cable.get('capacity'), + notes=cable.get('notes', '') + )) + + # Load pipelines + for pipeline in data.get('pipelines', []): + infra_type = type_map.get(pipeline.get('type'), InfrastructureType.GAS_PIPELINE) + + waypoints = [tuple(wp) for wp in pipeline.get('waypoints', [])] + + assets.append(InfrastructureAsset( + name=pipeline.get('name', 'Unknown'), + infra_type=infra_type, + waypoints=waypoints, + protection_radius_nm=pipeline.get('protection_radius_nm', 5.0), + operator=pipeline.get('operator'), + capacity=pipeline.get('capacity'), + notes=pipeline.get('notes', '') + )) + + # Load wind farms (as point assets) + for farm in data.get('wind_farms', []): + center = farm.get('center', [0, 0]) + assets.append(InfrastructureAsset( + name=farm.get('name', 'Unknown'), + infra_type=InfrastructureType.POWER_CABLE, # Treated as power infrastructure + latitude=center[0], + longitude=center[1], + protection_radius_nm=farm.get('protection_radius_nm', 2.0), + operator=farm.get('operator'), + capacity=f"{farm.get('capacity_mw', 0)} MW ({farm.get('turbines', 0)} turbines)", + notes=farm.get('notes', '') + )) + + print(f"Loaded {len(assets)} infrastructure assets from {filepath}") + return assets + + +def get_all_infrastructure() -> List['InfrastructureAsset']: + """ + Get all infrastructure assets, loading from JSON with fallback to hardcoded. + + Returns: + List of all infrastructure assets + """ + # Try loading from JSON first + json_assets = load_infrastructure_from_json() + + if json_assets: + return json_assets + + # Fallback to hardcoded Baltic infrastructure + return BALTIC_INFRASTRUCTURE + + @dataclass class InfrastructureProximityEvent: """Records when a vessel enters an infrastructure protection zone.""" @@ -402,7 +518,7 @@ def analyze_infrastructure_incident( IncidentAnalysis with full assessment """ if infrastructure is None: - infrastructure = BALTIC_INFRASTRUCTURE + infrastructure = get_all_infrastructure() if not track_history: return IncidentAnalysis( @@ -836,7 +952,7 @@ def _parse_timestamp(ts) -> datetime: # ============================================================================= def get_baltic_infrastructure() -> List[dict]: - """Get list of Baltic infrastructure for map display.""" + """Get list of all infrastructure for map display.""" return [ { "name": asset.name, @@ -849,7 +965,7 @@ def get_baltic_infrastructure() -> List[dict]: "capacity": asset.capacity, "notes": asset.notes } - for asset in BALTIC_INFRASTRUCTURE + for asset in get_all_infrastructure() ] From 80cff83452438270508497443bab8eeb1a73561a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Jan 2026 23:05:31 +0000 Subject: [PATCH 2/2] Add 10 communication cables to infrastructure database MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Baltic Sea telecom cables added: - BCS East-West Interlink (LT-SE) - damaged Nov 2024 - EESF-1 (EE-FI) - damaged Dec 2025 by Eagle S - EESF-2 (EE-FI) - redundancy cable - EE-S1 (EE-SE) - Arelion/Telia carrier - Eastern Light (SE-FI) - Nordic backbone - ROTACS (DE-EE) - Germany-Estonia link - Baltica (PL-SE) - Poland-Sweden link - Denmark-Sweden (Øresund crossing) - Finland-Sweden via Åland - Sweden-Latvia via Gotland --- data/infrastructure.json | 253 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) diff --git a/data/infrastructure.json b/data/infrastructure.json index e37b645..e75af19 100644 --- a/data/infrastructure.json +++ b/data/infrastructure.json @@ -341,6 +341,259 @@ "rfs_year": 2020, "protection_radius_nm": 3.0, "notes": "Sweden-Germany fiber cable via offshore wind farm area." + }, + { + "id": "bcs_ewi", + "name": "BCS East-West Interlink", + "type": "telecom", + "subtype": "fiber_optic", + "status": "damaged", + "region": "baltic_sea", + "waypoints": [ + [56.03, 21.07], + [56.30, 20.00], + [56.80, 19.00], + [57.20, 18.50], + [57.50, 18.30] + ], + "landing_points": [ + {"name": "Sventoji", "country": "LT", "lat": 56.03, "lon": 21.07}, + {"name": "Gotland (Katthammarsvik)", "country": "SE", "lat": 57.50, "lon": 18.30} + ], + "length_km": 218, + "operator": "Arelion (Telia Carrier)", + "capacity": "Multi-Tbps", + "rfs_year": 2017, + "protection_radius_nm": 5.0, + "notes": "Lithuania-Sweden telecom cable. Damaged Nov 17-18, 2024 during anchor drag incident.", + "incidents": [ + {"date": "2024-11-17", "type": "damage", "vessel": "Yi Peng 3", "description": "Anchor drag damage, Chinese bulk carrier suspected"} + ] + }, + { + "id": "eesf1", + "name": "EESF-1 (Estonia-Finland Submarine Cable)", + "type": "telecom", + "subtype": "fiber_optic", + "status": "damaged", + "region": "baltic_sea", + "waypoints": [ + [59.45, 24.75], + [59.60, 24.85], + [59.80, 25.00], + [59.95, 25.10] + ], + "landing_points": [ + {"name": "Tallinn", "country": "EE", "lat": 59.45, "lon": 24.75}, + {"name": "Helsinki", "country": "FI", "lat": 59.95, "lon": 25.10} + ], + "length_km": 75, + "operator": "Elisa", + "capacity": "High capacity", + "rfs_year": 2012, + "protection_radius_nm": 3.0, + "notes": "Finland-Estonia telecom cable. Damaged Dec 25, 2025 by Eagle S anchor drag.", + "incidents": [ + {"date": "2025-12-25", "type": "damage", "vessel": "Eagle S", "description": "Anchor drag damage, same incident as Estlink-2"} + ] + }, + { + "id": "eesf2", + "name": "EESF-2 (Estonia-Finland Submarine Cable 2)", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [59.43, 24.70], + [59.58, 24.82], + [59.75, 24.95], + [59.92, 25.08] + ], + "landing_points": [ + {"name": "Tallinn", "country": "EE", "lat": 59.43, "lon": 24.70}, + {"name": "Helsinki", "country": "FI", "lat": 59.92, "lon": 25.08} + ], + "length_km": 72, + "operator": "Elisa", + "capacity": "High capacity", + "rfs_year": 2016, + "protection_radius_nm": 3.0, + "notes": "Second Finland-Estonia telecom cable. Provides redundancy for EESF-1." + }, + { + "id": "ees1", + "name": "EE-S1 (Estonia-Sweden Cable)", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [59.40, 24.65], + [59.20, 23.00], + [59.00, 21.00], + [58.80, 19.50], + [58.70, 18.20] + ], + "landing_points": [ + {"name": "Tallinn", "country": "EE", "lat": 59.40, "lon": 24.65}, + {"name": "Nynäshamn", "country": "SE", "lat": 58.70, "lon": 18.20} + ], + "length_km": 420, + "operator": "Arelion (Telia Carrier)", + "capacity": "Multi-Tbps", + "rfs_year": 2019, + "protection_radius_nm": 4.0, + "notes": "Estonia-Sweden direct fiber link. Critical for Baltic region connectivity." + }, + { + "id": "eastern_light", + "name": "Eastern Light", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [59.30, 18.05], + [59.50, 19.50], + [59.80, 21.00], + [60.05, 22.50], + [60.15, 24.90] + ], + "landing_points": [ + {"name": "Stockholm", "country": "SE", "lat": 59.30, "lon": 18.05}, + {"name": "Helsinki", "country": "FI", "lat": 60.15, "lon": 24.90} + ], + "length_km": 500, + "operator": "Arelion", + "capacity": "Multi-Tbps", + "rfs_year": 2016, + "protection_radius_nm": 4.0, + "notes": "Sweden-Finland fiber optic cable. Part of Northern European backbone." + }, + { + "id": "rotacs", + "name": "ROTACS (Rostock-Tallinn Cable System)", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [54.18, 12.10], + [54.80, 13.50], + [55.50, 15.50], + [56.50, 18.00], + [57.80, 20.50], + [59.00, 22.50], + [59.45, 24.75] + ], + "landing_points": [ + {"name": "Rostock", "country": "DE", "lat": 54.18, "lon": 12.10}, + {"name": "Tallinn", "country": "EE", "lat": 59.45, "lon": 24.75} + ], + "length_km": 1100, + "operator": "Telia/Elisa", + "capacity": "High capacity", + "rfs_year": 2001, + "protection_radius_nm": 4.0, + "notes": "Germany-Estonia fiber cable crossing the Baltic Sea." + }, + { + "id": "baltica", + "name": "Baltica", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [54.35, 18.65], + [54.80, 17.50], + [55.10, 15.80], + [55.45, 14.80], + [55.60, 12.90] + ], + "landing_points": [ + {"name": "Gdynia", "country": "PL", "lat": 54.35, "lon": 18.65}, + {"name": "Trelleborg", "country": "SE", "lat": 55.60, "lon": 12.90} + ], + "length_km": 350, + "operator": "Polkomtel/Telia", + "capacity": "High capacity", + "rfs_year": 1999, + "protection_radius_nm": 3.0, + "notes": "Poland-Sweden fiber optic cable." + }, + { + "id": "denmark_sweden", + "name": "Denmark-Sweden Cable (Øresund)", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [55.68, 12.60], + [55.58, 12.75], + [55.50, 12.90] + ], + "landing_points": [ + {"name": "Copenhagen", "country": "DK", "lat": 55.68, "lon": 12.60}, + {"name": "Malmö", "country": "SE", "lat": 55.50, "lon": 12.90} + ], + "length_km": 25, + "operator": "Multiple operators", + "capacity": "Multi-Tbps", + "rfs_year": 2000, + "protection_radius_nm": 2.0, + "notes": "Multiple fiber cables crossing the Øresund strait. Critical Nordic interconnect." + }, + { + "id": "finland_sweden_aland", + "name": "Finland-Sweden via Åland", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [60.45, 22.20], + [60.10, 19.95], + [59.80, 19.20], + [59.30, 18.05] + ], + "landing_points": [ + {"name": "Turku", "country": "FI", "lat": 60.45, "lon": 22.20}, + {"name": "Mariehamn", "country": "AX", "lat": 60.10, "lon": 19.95}, + {"name": "Stockholm", "country": "SE", "lat": 59.30, "lon": 18.05} + ], + "length_km": 300, + "operator": "Cinia/Arelion", + "capacity": "High capacity", + "rfs_year": 2010, + "protection_radius_nm": 3.0, + "notes": "Telecom cable route through Åland archipelago connecting Finland and Sweden." + }, + { + "id": "sweden_latvia", + "name": "Sweden-Latvia Cable", + "type": "telecom", + "subtype": "fiber_optic", + "status": "operational", + "region": "baltic_sea", + "waypoints": [ + [57.60, 18.30], + [57.30, 19.50], + [57.00, 21.00], + [56.95, 24.10] + ], + "landing_points": [ + {"name": "Gotland", "country": "SE", "lat": 57.60, "lon": 18.30}, + {"name": "Riga", "country": "LV", "lat": 56.95, "lon": 24.10} + ], + "length_km": 380, + "operator": "LVRTC/Telia", + "capacity": "High capacity", + "rfs_year": 2004, + "protection_radius_nm": 3.0, + "notes": "Sweden-Latvia submarine fiber cable via Gotland." } ], "pipelines": [