131 lines
4.9 KiB
Python
131 lines
4.9 KiB
Python
# FlightMonitor/data/area_profile_manager.py
|
|
"""
|
|
Manages loading, saving, and handling of geographic area profiles.
|
|
"""
|
|
import json
|
|
import os
|
|
from typing import Dict, Optional, List
|
|
|
|
from flightmonitor.utils.logger import get_logger
|
|
from flightmonitor.data import config as app_config
|
|
|
|
module_logger = get_logger(__name__)
|
|
|
|
PROFILE_FILENAME = "area_profiles.json"
|
|
DEFAULT_PROFILE_NAME = "Default Zone"
|
|
|
|
|
|
class AreaProfileManager:
|
|
"""
|
|
Handles reading from and writing to the area profiles JSON file.
|
|
"""
|
|
|
|
def __init__(self, profiles_directory: str = "config"):
|
|
"""
|
|
Initializes the AreaProfileManager.
|
|
|
|
Args:
|
|
profiles_directory: The directory where the profiles file will be stored.
|
|
"""
|
|
self.profiles_path = os.path.join(
|
|
os.path.abspath(profiles_directory), PROFILE_FILENAME
|
|
)
|
|
self._profiles: Dict[str, Dict[str, float]] = {}
|
|
self._load_profiles()
|
|
|
|
def _create_default_profile(self) -> Dict[str, float]:
|
|
"""Creates the default profile from the application config."""
|
|
return {
|
|
"lat_min": app_config.DEFAULT_BBOX_LAT_MIN,
|
|
"lon_min": app_config.DEFAULT_BBOX_LON_MIN,
|
|
"lat_max": app_config.DEFAULT_BBOX_LAT_MAX,
|
|
"lon_max": app_config.DEFAULT_BBOX_LON_MAX,
|
|
}
|
|
|
|
def _load_profiles(self):
|
|
"""Loads profiles from the JSON file and ensures the default profile exists."""
|
|
# Start with the mandatory default profile
|
|
self._profiles = {DEFAULT_PROFILE_NAME: self._create_default_profile()}
|
|
|
|
if os.path.exists(self.profiles_path):
|
|
try:
|
|
with open(self.profiles_path, "r") as f:
|
|
user_profiles = json.load(f)
|
|
if isinstance(user_profiles, dict):
|
|
# Merge user profiles, default profile cannot be overwritten
|
|
for name, data in user_profiles.items():
|
|
if name != DEFAULT_PROFILE_NAME:
|
|
self._profiles[name] = data
|
|
module_logger.info(
|
|
f"Loaded {len(user_profiles)} user profiles from {self.profiles_path}"
|
|
)
|
|
except (json.JSONDecodeError, IOError) as e:
|
|
module_logger.error(
|
|
f"Error loading profiles from {self.profiles_path}: {e}"
|
|
)
|
|
else:
|
|
module_logger.info(
|
|
"Area profiles file not found. Starting with default profile."
|
|
)
|
|
# We can optionally save the default profile to create the file on first run
|
|
self._save_profiles()
|
|
|
|
def _save_profiles(self):
|
|
"""Saves the current user-defined profiles to the JSON file."""
|
|
# Ensure the directory exists
|
|
try:
|
|
os.makedirs(os.path.dirname(self.profiles_path), exist_ok=True)
|
|
except OSError as e:
|
|
module_logger.error(f"Could not create directory for profiles file: {e}")
|
|
return
|
|
|
|
# Prepare user-defined profiles for saving (exclude the default)
|
|
profiles_to_save = {
|
|
name: data
|
|
for name, data in self._profiles.items()
|
|
if name != DEFAULT_PROFILE_NAME
|
|
}
|
|
|
|
try:
|
|
with open(self.profiles_path, "w") as f:
|
|
json.dump(profiles_to_save, f, indent=4)
|
|
module_logger.info(
|
|
f"Successfully saved {len(profiles_to_save)} profiles to {self.profiles_path}"
|
|
)
|
|
except IOError as e:
|
|
module_logger.error(f"Error saving profiles to {self.profiles_path}: {e}")
|
|
|
|
def get_profile_names(self) -> List[str]:
|
|
"""Returns a sorted list of all available profile names."""
|
|
return sorted(self._profiles.keys())
|
|
|
|
def get_profile_data(self, name: str) -> Optional[Dict[str, float]]:
|
|
"""Returns the BBox data for a given profile name."""
|
|
return self._profiles.get(name)
|
|
|
|
def save_profile(self, name: str, data: Dict[str, float]) -> bool:
|
|
"""
|
|
Saves a new or updated profile. Returns False if name is invalid or default.
|
|
"""
|
|
if not name or name == DEFAULT_PROFILE_NAME:
|
|
module_logger.warning(
|
|
f"Attempt to save invalid or default profile name: '{name}'"
|
|
)
|
|
return False
|
|
|
|
self._profiles[name] = data
|
|
self._save_profiles()
|
|
return True
|
|
|
|
def delete_profile(self, name: str) -> bool:
|
|
"""Deletes a profile. Returns False if the profile is default or not found."""
|
|
if name == DEFAULT_PROFILE_NAME:
|
|
module_logger.warning("Cannot delete the default profile.")
|
|
return False
|
|
if name in self._profiles:
|
|
del self._profiles[name]
|
|
self._save_profiles()
|
|
return True
|
|
module_logger.warning(f"Profile '{name}' not found for deletion.")
|
|
return False
|