Добавил альтернативное имя у спутника
This commit is contained in:
@@ -5,12 +5,99 @@ from io import BytesIO
|
||||
|
||||
# Third-party imports
|
||||
import requests
|
||||
from django.db.models import Q
|
||||
|
||||
# Local imports
|
||||
from mainapp.models import Polarization, Satellite
|
||||
|
||||
from .models import Transponders
|
||||
|
||||
|
||||
def parse_satellite_name(full_name: str) -> tuple[str, str | None]:
|
||||
"""
|
||||
Парсит полное имя спутника и извлекает основное и альтернативное имя.
|
||||
|
||||
Альтернативное имя находится в скобках после основного названия.
|
||||
Примеры:
|
||||
"Koreasat 116 (ANASIS-II)" -> ("Koreasat 116", "ANASIS-II")
|
||||
"Thaicom 6 (Africom 1)" -> ("Thaicom 6", "Africom 1")
|
||||
"Express AM6" -> ("Express AM6", None)
|
||||
|
||||
Args:
|
||||
full_name: Полное имя спутника (может содержать альтернативное имя в скобках)
|
||||
|
||||
Returns:
|
||||
tuple: (основное_имя, альтернативное_имя или None)
|
||||
"""
|
||||
if not full_name:
|
||||
return (full_name, None)
|
||||
|
||||
# Ищем текст в скобках в конце строки
|
||||
match = re.match(r'^(.+?)\s*\(([^)]+)\)\s*$$', full_name.strip())
|
||||
if match:
|
||||
main_name = match.group(1).strip()
|
||||
alt_name = match.group(2).strip()
|
||||
return (main_name, alt_name)
|
||||
|
||||
return (full_name.strip(), None)
|
||||
|
||||
|
||||
def find_satellite_by_name(name: str):
|
||||
"""
|
||||
Ищет спутник по имени или альтернативному имени.
|
||||
|
||||
Все сравнения выполняются в lowercase.
|
||||
|
||||
Алгоритм поиска:
|
||||
1. Точное совпадение по name (lowercase)
|
||||
2. Точное совпадение по alternative_name (lowercase)
|
||||
3. Частичное совпадение по name (lowercase)
|
||||
4. Частичное совпадение по alternative_name (lowercase)
|
||||
|
||||
Args:
|
||||
name: Имя спутника для поиска
|
||||
|
||||
Returns:
|
||||
Satellite или None: Найденный спутник или None
|
||||
|
||||
Raises:
|
||||
Satellite.MultipleObjectsReturned: Если найдено несколько спутников
|
||||
"""
|
||||
if not name:
|
||||
return None
|
||||
|
||||
name_lower = name.strip().lower()
|
||||
|
||||
# 1. Точное совпадение по name (lowercase)
|
||||
try:
|
||||
return Satellite.objects.get(name__iexact=name_lower)
|
||||
except Satellite.DoesNotExist:
|
||||
pass
|
||||
except Satellite.MultipleObjectsReturned:
|
||||
raise
|
||||
|
||||
# 2. Точное совпадение по alternative_name (lowercase)
|
||||
try:
|
||||
return Satellite.objects.get(alternative_name__iexact=name_lower)
|
||||
except Satellite.DoesNotExist:
|
||||
pass
|
||||
except Satellite.MultipleObjectsReturned:
|
||||
raise
|
||||
|
||||
# 3. Частичное совпадение по name или alternative_name (lowercase)
|
||||
satellites = Satellite.objects.filter(
|
||||
Q(name__icontains=name_lower) | Q(alternative_name__icontains=name_lower)
|
||||
)
|
||||
|
||||
if satellites.count() == 1:
|
||||
return satellites.first()
|
||||
elif satellites.count() > 1:
|
||||
raise Satellite.MultipleObjectsReturned(
|
||||
f"Найдено несколько спутников с именем '{name_lower}'"
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
def search_satellite_on_page(data: dict, satellite_name: str):
|
||||
for pos, value in data.get('page', {}).get('positions').items():
|
||||
for name in value['satellites']:
|
||||
@@ -82,13 +169,19 @@ def parse_transponders_from_json(filepath: str, user=None):
|
||||
"""
|
||||
Парсит транспондеры из JSON файла.
|
||||
|
||||
Если имя спутника содержит альтернативное имя в скобках, оно извлекается
|
||||
и сохраняется в поле alternative_name.
|
||||
|
||||
Args:
|
||||
filepath: путь к JSON файлу
|
||||
user: пользователь для установки created_by и updated_by (optional)
|
||||
"""
|
||||
with open(filepath, encoding="utf-8") as jf:
|
||||
data = json.load(jf)
|
||||
for sat_name, trans_zone in data["satellites"].items():
|
||||
for sat_name_full, trans_zone in data["satellites"].items():
|
||||
# Парсим имя спутника и альтернативное имя
|
||||
main_name, alt_name = parse_satellite_name(sat_name_full)
|
||||
|
||||
for zone, trans in trans_zone.items():
|
||||
for tran in trans:
|
||||
f_b, f_e = tran["freq"][0].split("-")
|
||||
@@ -96,7 +189,19 @@ def parse_transponders_from_json(filepath: str, user=None):
|
||||
f_range = round(abs(float(f_e) - float(f_b)), 3)
|
||||
|
||||
pol_obj = Polarization.objects.get(name=tran["pol"])
|
||||
sat_obj = Satellite.objects.get(name__iexact=sat_name)
|
||||
|
||||
# Ищем спутник по имени или альтернативному имени
|
||||
sat_obj = find_satellite_by_name(main_name)
|
||||
if not sat_obj:
|
||||
# Если не найден, создаём новый с альтернативным именем
|
||||
sat_obj = Satellite.objects.create(
|
||||
name=main_name,
|
||||
alternative_name=alt_name
|
||||
)
|
||||
elif alt_name and not sat_obj.alternative_name:
|
||||
# Если найден, но альтернативное имя не установлено - обновляем
|
||||
sat_obj.alternative_name = alt_name
|
||||
sat_obj.save()
|
||||
|
||||
tran_obj, created = Transponders.objects.get_or_create(
|
||||
name=tran["name"],
|
||||
@@ -124,6 +229,9 @@ def parse_transponders_from_xml(data_in: BytesIO, user=None):
|
||||
"""
|
||||
Парсит транспондеры из XML файла.
|
||||
|
||||
Если имя спутника содержит альтернативное имя в скобках, оно извлекается
|
||||
и сохраняется в поле alternative_name.
|
||||
|
||||
Args:
|
||||
data_in: BytesIO объект с XML данными
|
||||
user: пользователь для установки created_by и updated_by (optional)
|
||||
@@ -136,9 +244,13 @@ def parse_transponders_from_xml(data_in: BytesIO, user=None):
|
||||
}
|
||||
satellites = tree.xpath('//ns:SatelliteMemo', namespaces=ns)
|
||||
for sat in satellites[:]:
|
||||
name = sat.xpath('./ns:name/text()', namespaces=ns)[0]
|
||||
if name == 'X' or 'DONT USE' in name:
|
||||
name_full = sat.xpath('./ns:name/text()', namespaces=ns)[0]
|
||||
if name_full == 'X' or 'DONT USE' in name_full:
|
||||
continue
|
||||
|
||||
# Парсим имя спутника и альтернативное имя
|
||||
main_name, alt_name = parse_satellite_name(name_full)
|
||||
|
||||
norad = sat.xpath('./ns:norad/text()', namespaces=ns)
|
||||
beams = sat.xpath('.//ns:BeamMemo', namespaces=ns)
|
||||
intl_code = sat.xpath('.//ns:internationalCode/text()', namespaces=ns)
|
||||
@@ -158,7 +270,6 @@ def parse_transponders_from_xml(data_in: BytesIO, user=None):
|
||||
uplink_start = float(transponder.xpath('./ns:uplinkFrequency/tr:start/text()', namespaces=ns)[0])
|
||||
uplink_end = float(transponder.xpath('./ns:uplinkFrequency/tr:end/text()', namespaces=ns)[0])
|
||||
tr_data = zones[tr_id]
|
||||
# p = tr_data['pol'][0] if tr_data['pol'] else '-'
|
||||
match tr_data['pol']:
|
||||
case 'Horizontal':
|
||||
pol = 'Горизонтальная'
|
||||
@@ -173,13 +284,36 @@ def parse_transponders_from_xml(data_in: BytesIO, user=None):
|
||||
tr_name = transponder.xpath('./ns:name/text()', namespaces=ns)[0]
|
||||
|
||||
pol_obj, _ = Polarization.objects.get_or_create(name=pol)
|
||||
sat_obj, _ = Satellite.objects.get_or_create(
|
||||
name=name,
|
||||
defaults={
|
||||
"norad": int(norad[0]) if norad else -1,
|
||||
"international_code": intl_code[0] if intl_code else "",
|
||||
"undersat_point": sub_sat_point[0 if sub_sat_point else ""]
|
||||
})
|
||||
|
||||
# Ищем спутник по имени или альтернативному имени
|
||||
sat_obj = find_satellite_by_name(main_name)
|
||||
if not sat_obj:
|
||||
# Если не найден, создаём новый с альтернативным именем
|
||||
sat_obj = Satellite.objects.create(
|
||||
name=main_name,
|
||||
alternative_name=alt_name,
|
||||
norad=int(norad[0]) if norad else -1,
|
||||
international_code=intl_code[0] if intl_code else "",
|
||||
undersat_point=float(sub_sat_point[0]) if sub_sat_point else None
|
||||
)
|
||||
else:
|
||||
# Если найден, обновляем альтернативное имя если не установлено
|
||||
updated = False
|
||||
if alt_name and not sat_obj.alternative_name:
|
||||
sat_obj.alternative_name = alt_name
|
||||
updated = True
|
||||
if norad and not sat_obj.norad:
|
||||
sat_obj.norad = int(norad[0])
|
||||
updated = True
|
||||
if intl_code and not sat_obj.international_code:
|
||||
sat_obj.international_code = intl_code[0]
|
||||
updated = True
|
||||
if sub_sat_point and not sat_obj.undersat_point:
|
||||
sat_obj.undersat_point = float(sub_sat_point[0])
|
||||
updated = True
|
||||
if updated:
|
||||
sat_obj.save()
|
||||
|
||||
trans_obj, created = Transponders.objects.get_or_create(
|
||||
polarization=pol_obj,
|
||||
downlink=(downlink_start+downlink_end)/2/1000000,
|
||||
|
||||
Reference in New Issue
Block a user