From b76948ecf96f1eaf0d76368454c55c4dcb5249d4 Mon Sep 17 00:00:00 2001 From: Mariano Daniel Gobea Alcoba Date: Mon, 20 May 2024 19:34:18 -0300 Subject: [PATCH] :sparkles: SatelliteServices finished --- main.py | 9 ++++--- requirementes.txt | 39 +++++++++++++++++++++++++++++ requirements.txt | 3 +++ services/satellites_services.py | 44 ++++++++++++++++++++++++++++----- 4 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 requirementes.txt diff --git a/main.py b/main.py index 34abcf2..6f095d2 100644 --- a/main.py +++ b/main.py @@ -60,13 +60,13 @@ async def top_secret( } } )] -) -> Coordinates | Response: +) -> dict | Response: """ This endpoint receives a list of satellites with the information of the distance and the message that they sent. - It returns the coordinates of the point where the message was sent. + It returns the coordinates of the point where the message was sent and the complete message. :param request: Request model with the list of satellites. - :return: Coordinates model with the coordinates of the point where the message was sent. + :return: Dictionary with the coordinates of the point where the message was sent and the complete message. """ try: satellites: List[Satellite] = request.satellites @@ -74,7 +74,8 @@ async def top_secret( SatelliteService.add_satellite(satellite) coordinates: Coordinates = SatelliteService.get_coordinates(satellites) - return coordinates + message: str = SatelliteService.get_message(satellites) + return {"coordinates": coordinates, "message": message} except Exception as e: return JSONResponse(status_code=404, content={"message ": str(e)}) diff --git a/requirementes.txt b/requirementes.txt new file mode 100644 index 0000000..e6ffa25 --- /dev/null +++ b/requirementes.txt @@ -0,0 +1,39 @@ +annotated-types==0.6.0 +anyio==4.3.0 +certifi==2024.2.2 +click==8.1.7 +dnspython==2.6.1 +email_validator==2.1.1 +fastapi==0.111.0 +fastapi-cli==0.0.4 +FastAPI-SQLAlchemy==0.2.1 +h11==0.14.0 +httpcore==1.0.5 +httptools==0.6.1 +httpx==0.27.0 +idna==3.7 +Jinja2==3.1.4 +markdown-it-py==3.0.0 +MarkupSafe==2.1.5 +mdurl==0.1.2 +numpy==1.26.4 +orjson==3.10.3 +pydantic==2.7.1 +pydantic_core==2.18.2 +Pygments==2.18.0 +python-dotenv==1.0.1 +python-multipart==0.0.9 +PyYAML==6.0.1 +rich==13.7.1 +scipy==1.13.0 +shellingham==1.5.4 +sniffio==1.3.1 +SQLAlchemy==2.0.30 +starlette==0.37.2 +typer==0.12.3 +typing_extensions==4.11.0 +ujson==5.10.0 +uvicorn==0.29.0 +uvloop==0.19.0 +watchfiles==0.21.0 +websockets==12.0 diff --git a/requirements.txt b/requirements.txt index 684efd9..0252569 100644 --- a/requirements.txt +++ b/requirements.txt @@ -35,3 +35,6 @@ uvicorn==0.29.0 uvloop==0.19.0 watchfiles==0.21.0 websockets==12.0 + +numpy~=1.26.4 +scipy~=1.13.0 \ No newline at end of file diff --git a/services/satellites_services.py b/services/satellites_services.py index c7bcbf8..48c8307 100644 --- a/services/satellites_services.py +++ b/services/satellites_services.py @@ -1,13 +1,15 @@ from sqlalchemy.orm import Session from model.data_class import Satellite, Coordinates from repository.database import SatelliteDB, satellite_to_db, db_to_satellite, Session +from scipy.optimize import minimize +import numpy as np + class SatelliteService(object): session: Session = Session() @classmethod def add_satellite(cls, satellite: Satellite) -> None: - satellite_db = cls.session.query(SatelliteDB).filter(SatelliteDB.name == satellite.name).first() if satellite_db: satellite_db.distance = satellite.distance @@ -43,12 +45,42 @@ def get_satellites(cls) -> list[Satellite]: @classmethod def get_coordinates(cls, satellites: list[Satellite]) -> Coordinates: - return Coordinates(x=0.0, y=0.0) + # Definir la función objetivo para minimizar + def objective(x, locations, distances): + return sum([(np.linalg.norm(x - locations[i]) - distances[i]) ** 2 for i in range(len(locations))]) + + # Obtener las ubicaciones y distancias de los satélites + locations = np.array([np.array([satellite.coordinates.x, satellite.coordinates.y]) for satellite in satellites]) + distances = np.array([satellite.distance for satellite in satellites]) + + # Estimar la ubicación inicial como el centroide de las ubicaciones de los satélites + x0 = np.mean(locations, axis=0) + + # Minimizar la función objetivo + result = minimize(objective, x0, args=(locations, distances), method='L-BFGS-B') + + # Devolver las coordenadas resultantes + return Coordinates(x=result.x[0], y=result.x[1]) @classmethod def get_message(cls, satellites: list[Satellite]) -> str: - return "This is a message" + # Crear una lista de listas para almacenar los fragmentos de mensajes de cada satélite + message_fragments = [satellite.message for satellite in satellites] + + # Crear una lista vacía para almacenar el mensaje reconstruido + message = [] + + # Iterar sobre las listas de fragmentos de mensajes en paralelo + for fragments in zip(*message_fragments): + # Agregar al mensaje el primer fragmento que no sea una cadena vacía + for fragment in fragments: + if fragment: + message.append(fragment) + break + + # Unir los fragmentos de mensajes en un solo mensaje + message = " ".join(message) + + # Devolver el mensaje + return message - @classmethod - def get_distance(cls, satellites: list[Satellite]) -> float: - return 100.0 \ No newline at end of file