Sada bugfixu

This commit is contained in:
Michal Kváček
2024-08-12 06:27:28 +02:00
parent 9e6b0b574c
commit 94639da820
6 changed files with 174 additions and 190 deletions
+29 -91
View File
@@ -1,16 +1,14 @@
import asyncio
import random
import uuid
from typing import List, Optional
from sqlalchemy import delete, insert, select, func, text
from typing import Optional
from sqlalchemy import delete, insert
from sqlalchemy.ext.asyncio import AsyncSession
from strawberry.file_uploads import Upload
from background_jobs.elevation import add_terrain_elevation_to_flight
from utils.flight_track_helpers import handle_upload_gpx, save_track_from_gpx_to_db, extract_basic_flight_info_from_gpx
from background_jobs.weather import download_weather_for_flight
from database import models
from database.models import flight_has_copilot
from database.transaction import get_session
from external.gpx_parser import GPXParser
from graphql_schema.entities.helpers.combobox import handle_combobox_save
from graphql_schema.entities.resolvers.base import BaseMutationResolver, BaseQueryResolver
from graphql_schema.entities.types.mutation_input import (
@@ -18,9 +16,8 @@ from graphql_schema.entities.types.mutation_input import (
)
from graphql_schema.entities.types.types import Flight
from paths import FLIGHT_GPX_TRACK_PATH
from utils.file import delete_file
from utils.str_utils import random_str
from utils.file import handle_file_upload
from utils.str_utils import random_str
class FlightQueryResolver(BaseQueryResolver):
@@ -75,55 +72,13 @@ class FlightMutationResolver(BaseMutationResolver):
def __init__(self):
super().__init__(Flight, models.Flight)
async def get_airport_id_by_gps(self, gps_lat: float, gps_lng: float) -> Optional[int]:
async with (get_session() as db):
query = (
select(models.Airport, func.coalesce(6371 * func.acos(
func.cos(func.radians(gps_lat)) *
func.cos(func.radians(models.Airport.gps_latitude)) *
func.cos(func.radians(models.Airport.gps_longitude) - func.radians(gps_lng)) +
func.sin(func.radians(gps_lat)) *
func.sin(func.radians(models.Airport.gps_latitude))
), 9999).label("distance"))
.filter(models.Airport.use_in_gpx_guess.is_(True))
.order_by("distance")
.having(text("distance < 1"))
.limit(1)
)
data = (await db.execute(query)).one_or_none()
if data:
airport, distance = data
return airport.id
return None
async def extract_data_from_gpx(self, gpx_filename: str) -> dict:
data = GPXParser(f"{FLIGHT_GPX_TRACK_PATH}/{gpx_filename}")
times, coordinates = await asyncio.gather(
data.get_times(),
data.get_coordinates()
)
takeoff_airport_id, landing_airport_id = await asyncio.gather(
self.get_airport_id_by_gps(coordinates[0]['lat'], coordinates[0]['lng']),
self.get_airport_id_by_gps(coordinates[-1]['lat'], coordinates[-1]['lng']),
)
return {
"takeoff_airport_id": takeoff_airport_id,
"landing_airport_id": landing_airport_id,
"takeoff_datetime": times[0],
"landing_datetime": times[-1],
}
async def create(self, context, input: CreateFlightInput) -> Flight:
data = input.to_dict()
user_id = context.user_id
if input.gpx_track_file:
data['gpx_track_filename'] = await handle_upload_gpx(gpx_track=input.gpx_track_file, context=context)
data_from_gpx = await self.extract_data_from_gpx(data['gpx_track_filename'])
data['gpx_track_filename'] = await handle_file_upload(input.gpx_track_file, FLIGHT_GPX_TRACK_PATH)
data_from_gpx = await extract_basic_flight_info_from_gpx(data['gpx_track_filename'])
data.update(data_from_gpx)
else:
async with get_session() as db:
@@ -153,16 +108,10 @@ class FlightMutationResolver(BaseMutationResolver):
if input.track is not None:
await handle_track_edit(db=db, flight_id=flight.id, track=input.track, user_id=user_id)
context.background_tasks.add_task(
download_weather_for_flight,
flight_id=flight.id, airport_id=flight.takeoff_airport_id, date_time=flight.takeoff_datetime,
type_="takeoff"
)
context.background_tasks.add_task(
download_weather_for_flight,
flight_id=flight.id, airport_id=flight.landing_airport_id, date_time=flight.landing_datetime,
type_="landing"
)
if data['gpx_track_filename']:
await save_track_from_gpx_to_db(gpx_filename=data['gpx_track_filename'], flight_id=flight.id)
schedule_background_tasks(flight.id, data, context)
return flight
@@ -176,40 +125,23 @@ class FlightMutationResolver(BaseMutationResolver):
data = input.to_dict()
if input.gpx_track_file is not None:
data['gpx_track_filename'] = await handle_upload_gpx(
gpx_track=input.gpx_track_file,
context=context,
original_gpx_filename=flight_data['gpx_track_filename']
)
data['gpx_track_filename'] = await handle_upload_gpx(gpx_track=input.gpx_track_file, flight_id=flight_id)
async with get_session() as db:
if input.takeoff_airport:
takeoff_airport_id = await handle_combobox_save(
data['takeoff_airport_id'] = await handle_combobox_save(
db, models.Airport, input.takeoff_airport, user_id, name_column="icao_code",
extra_data={"name": input.takeoff_airport.name}
)
data['takeoff_airport_id'] = takeoff_airport_id
data['takeoff_datetime'] = input.takeoff_datetime or flight_data['takeoff_datetime']
context.background_tasks.add_task(
download_weather_for_flight, flight_id=id, airport_id=takeoff_airport_id, date_time=data['takeoff_datetime'],
type_="takeoff"
)
if input.landing_airport:
landing_airport_id = await handle_combobox_save(
data['landing_airport_id'] = await handle_combobox_save(
db, models.Airport, input.landing_airport, user_id, name_column="icao_code",
extra_data={"name": input.landing_airport.name}
)
data['landing_airport_id'] = landing_airport_id
data['landing_datetime'] = input.landing_datetime or flight_data['landing_datetime']
context.background_tasks.add_task(
download_weather_for_flight, flight_id=id, airport_id=landing_airport_id, date_time=data['landing_datetime'],
type_="landing"
)
if input.aircraft is not None:
data['aircraft_id'] = await handle_aircraft_save(db, user_id, input.aircraft)
@@ -238,20 +170,26 @@ class FlightMutationResolver(BaseMutationResolver):
token=random_str(64)
))
return await self._do_update(db, flight_data, data)
flight_model = await self._do_update(db, flight_data, data)
schedule_background_tasks(flight_id, data, context)
return flight_model
async def handle_upload_gpx(gpx_track: Upload, context, original_gpx_filename: Optional[str] = None):
if original_gpx_filename:
delete_file(FLIGHT_GPX_TRACK_PATH + "/" + original_gpx_filename, silent=True)
filename = await handle_file_upload(gpx_track, FLIGHT_GPX_TRACK_PATH)
context.background_tasks.add_task(add_terrain_elevation_to_flight, flight_id=id, gpx_filename=filename)
return filename
def schedule_background_tasks(flight_id: int, flight_data: dict, context) -> None:
context.background_tasks.add_task(add_terrain_elevation_to_flight, flight_id=flight_id)
context.background_tasks.add_task(
download_weather_for_flight, flight_id=id, airport_id=flight_data['takeoff_airport_id'],
date_time=flight_data['takeoff_datetime'], type_="takeoff"
)
context.background_tasks.add_task(
download_weather_for_flight, flight_id=id, airport_id=flight_data['landing_airport_id'],
date_time=flight_data['landing_datetime'], type_="landing"
)
async def handle_track_edit(db: AsyncSession, flight_id: int, track: List[TrackItemInput], user_id: int):
async def handle_track_edit(db: AsyncSession, flight_id: int, track: list[TrackItemInput], user_id: int):
await db.execute(delete(models.FlightTurnPoint).filter(models.FlightTurnPoint.flight_id == flight_id))
order = 0