From 6e8ec4f0f1c60393bd10adde2369e25719062ae4 Mon Sep 17 00:00:00 2001 From: shadowik Date: Wed, 16 Oct 2024 01:05:48 +0400 Subject: [PATCH] Change architecture, Main functionality, Little practise HTML template --- .../EvaluationEfficiencyOptimizationWind.iml | 18 +++- .idea/misc.xml | 5 +- .idea/other.xml | 6 ++ floris_module/src/__init__.py | 0 front/webpack.config.js | 2 +- .../floris_module}/.gitignore | 0 .../floris_module}/NOTES.md | 0 .../floris_module}/docs/Yaw_example.png | Bin .../floris_module}/requirements.txt | 0 .../floris_module}/src/FlorisULSTU.py | 35 +++++++- server/floris_module/src/__init__.py | 3 + .../floris_module}/src/gch.yaml | 10 +-- .../floris_module}/src/main.py | 0 server/main.py | 58 ------------ server/public/floris/Yaw_example.png | Bin 30675 -> 0 bytes server/src/data/database.py | 11 +++ server/{database.py => src/data/models.py} | 24 ++--- server/src/data/repository.py | 27 ++++++ server/src/data/schemas.py | 19 ++++ server/src/floris_router.py | 36 -------- server/src/main.py | 22 +++++ server/src/router.py | 1 - server/src/routers/floris_router.py | 73 +++++++++++++++ server/src/routers/floris_template_router.py | 65 ++++++++++++++ server/templates/floris_templates/main.html | 85 ++++++++++++++++++ server/templates/main.html | 43 --------- 26 files changed, 376 insertions(+), 167 deletions(-) create mode 100644 .idea/other.xml delete mode 100644 floris_module/src/__init__.py rename {floris_module => server/floris_module}/.gitignore (100%) rename {floris_module => server/floris_module}/NOTES.md (100%) rename {floris_module => server/floris_module}/docs/Yaw_example.png (100%) rename {floris_module => server/floris_module}/requirements.txt (100%) rename {floris_module => server/floris_module}/src/FlorisULSTU.py (54%) create mode 100644 server/floris_module/src/__init__.py rename {floris_module => server/floris_module}/src/gch.yaml (95%) rename {floris_module => server/floris_module}/src/main.py (100%) delete mode 100644 server/main.py delete mode 100644 server/public/floris/Yaw_example.png create mode 100644 server/src/data/database.py rename server/{database.py => src/data/models.py} (58%) create mode 100644 server/src/data/repository.py create mode 100644 server/src/data/schemas.py delete mode 100644 server/src/floris_router.py create mode 100644 server/src/main.py delete mode 100644 server/src/router.py create mode 100644 server/src/routers/floris_router.py create mode 100644 server/src/routers/floris_template_router.py create mode 100644 server/templates/floris_templates/main.html delete mode 100644 server/templates/main.html diff --git a/.idea/EvaluationEfficiencyOptimizationWind.iml b/.idea/EvaluationEfficiencyOptimizationWind.iml index d0876a7..32cf6f3 100644 --- a/.idea/EvaluationEfficiencyOptimizationWind.iml +++ b/.idea/EvaluationEfficiencyOptimizationWind.iml @@ -1,8 +1,22 @@ - - + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index d56657a..9af92d1 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ - + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..2e75c2e --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/floris_module/src/__init__.py b/floris_module/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/front/webpack.config.js b/front/webpack.config.js index d840890..a40ac79 100644 --- a/front/webpack.config.js +++ b/front/webpack.config.js @@ -5,7 +5,7 @@ import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'; const __dirname = path.resolve(); const config = { - entry: './src/index.tsx', + entry: './routers/index.tsx', output: { path: path.resolve(__dirname, 'dist'), filename: 'main.js', diff --git a/floris_module/.gitignore b/server/floris_module/.gitignore similarity index 100% rename from floris_module/.gitignore rename to server/floris_module/.gitignore diff --git a/floris_module/NOTES.md b/server/floris_module/NOTES.md similarity index 100% rename from floris_module/NOTES.md rename to server/floris_module/NOTES.md diff --git a/floris_module/docs/Yaw_example.png b/server/floris_module/docs/Yaw_example.png similarity index 100% rename from floris_module/docs/Yaw_example.png rename to server/floris_module/docs/Yaw_example.png diff --git a/floris_module/requirements.txt b/server/floris_module/requirements.txt similarity index 100% rename from floris_module/requirements.txt rename to server/floris_module/requirements.txt diff --git a/floris_module/src/FlorisULSTU.py b/server/floris_module/src/FlorisULSTU.py similarity index 54% rename from floris_module/src/FlorisULSTU.py rename to server/floris_module/src/FlorisULSTU.py index 405a632..d0971ac 100644 --- a/floris_module/src/FlorisULSTU.py +++ b/server/floris_module/src/FlorisULSTU.py @@ -1,4 +1,14 @@ +import os.path +import sys +import uuid +from pathlib import Path + from floris import FlorisModel +from floris.flow_visualization import visualize_cut_plane +from floris.layout_visualization import plot_turbine_labels +import floris.layout_visualization as layoutviz + +import matplotlib.pyplot as plt _wind_direction_to_val: dict[str, float] = { @@ -31,13 +41,34 @@ def _check_wind_direction_definition(wind_direction: str) -> bool: class FlorisULSTU(FlorisModel): - def __init__(self, url_yaml): + def __init__( + self, + url_yaml: Path = Path(__file__).parent / "gch.yaml" + ): super().__init__(url_yaml) def set(self, **kwargs): - if ("wind_directions" in kwargs) and (kwargs["wind_directions"] is list[str]): + if ("wind_directions" in kwargs) and (type(kwargs["wind_directions"][0]) is str): kwargs["wind_directions"] = _convert_winds_list_direction_definitions(kwargs["wind_directions"]) super().set(**kwargs) + def visualisation(self): + + + self.reset_operation() + + horizontal_plane = self.calculate_horizontal_plane(height=90.0) + visualize_cut_plane( + horizontal_plane, + ) + + # plot_turbine_labels(self, axarr[0, 0]) + filename = str(uuid.uuid4()) + ".png" + plt.savefig(Path(__file__).parent.parent.parent / f"public/floris/{filename}") + plt.close() + + return filename + + diff --git a/server/floris_module/src/__init__.py b/server/floris_module/src/__init__.py new file mode 100644 index 0000000..4cc26c6 --- /dev/null +++ b/server/floris_module/src/__init__.py @@ -0,0 +1,3 @@ +from .FlorisULSTU import FlorisULSTU + +__all__ = ['FlorisULSTU'] \ No newline at end of file diff --git a/floris_module/src/gch.yaml b/server/floris_module/src/gch.yaml similarity index 95% rename from floris_module/src/gch.yaml rename to server/floris_module/src/gch.yaml index 5c0ea8e..01d727d 100644 --- a/floris_module/src/gch.yaml +++ b/server/floris_module/src/gch.yaml @@ -149,9 +149,9 @@ flow_field: wake: ### - # Select the models to use for the simulation. + # Select the data to use for the simulation. # See :py:mod:`~.wake` for a list - # of available models and their descriptions. + # of available data and their descriptions. model_strings: ### @@ -190,7 +190,7 @@ wake: # Configure the parameters for the wake deflection model # selected above. # Additional blocks can be provided for - # models that are not enabled, but the enabled model + # data that are not enabled, but the enabled model # must have a corresponding parameter block. wake_deflection_parameters: gauss: @@ -210,7 +210,7 @@ wake: # Configure the parameters for the wake velocity deficit model # selected above. # Additional blocks can be provided for - # models that are not enabled, but the enabled model + # data that are not enabled, but the enabled model # must have a corresponding parameter block. wake_velocity_parameters: cc: @@ -234,7 +234,7 @@ wake: # Configure the parameters for the wake turbulence model # selected above. # Additional blocks can be provided for - # models that are not enabled, but the enabled model + # data that are not enabled, but the enabled model # must have a corresponding parameter block. wake_turbulence_parameters: crespo_hernandez: diff --git a/floris_module/src/main.py b/server/floris_module/src/main.py similarity index 100% rename from floris_module/src/main.py rename to server/floris_module/src/main.py diff --git a/server/main.py b/server/main.py deleted file mode 100644 index d523ca6..0000000 --- a/server/main.py +++ /dev/null @@ -1,58 +0,0 @@ -from fastapi import FastAPI, Depends, Request -from fastapi.responses import RedirectResponse, HTMLResponse -from sqlalchemy.orm import Session -from sqlalchemy.future import select -from database import SessionLocal, User, Base, engine -from fastapi.templating import Jinja2Templates -from fastapi.staticfiles import StaticFiles - -from src.floris_router import router as floris_router -from src.floris_router import get_images - -Base.metadata.create_all(bind=engine) - -app = FastAPI() -templates = Jinja2Templates(directory="templates") - -app.mount("/static", StaticFiles(directory="static"), name="static") -app.mount("/public", StaticFiles(directory="public"), name="public") - -app.include_router(floris_router) - - -def get_db(): - db = SessionLocal() - try: - yield db - finally: - db.close() - - -@app.get("/hello") -async def hello(): - return {"message": "Hello, World!"} - - -@app.get("/") -async def redirect_to_docs(): - return RedirectResponse(url="/docs") - - -@app.get("/users") -def read_users(db: Session = Depends(get_db)): - result = db.execute(select(User)) - users = result.scalars().all() # Получаем всех пользователей - return users - - -@app.get("/main", response_class=HTMLResponse) -async def main(request: Request): - params = {"request": request} - params.update(await get_images()) - - return templates.TemplateResponse("main.html", params) - - -if __name__ == "__main__": - import uvicorn - uvicorn.run(app, host="localhost", port=8080) # Изменено на localhost diff --git a/server/public/floris/Yaw_example.png b/server/public/floris/Yaw_example.png deleted file mode 100644 index 7b4d7b59ba75762e616e39bed540c3f9ea73b361..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30675 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 SFlorisInputParams | None: + + if not all([options, x, y]): + return None + + return SFlorisInputParams( + weather_id=int(options), + layout_x=list(map(float, x.split())), + layout_y=list(map(float, y.split())), + ) + + +@router.post("/", response_class=HTMLResponse) +async def post_main( + request: Request, + windmill_params: Annotated[SFlorisInputParams | None, Depends(transform_windmill_data)] = None, +): + if windmill_params is None: + return await get_main(request) + + data = await get_windmill_data(windmill_params) + context = { + 'data': data.data, + 'file_name': data.file_name, + } + + return await get_main(request, context) diff --git a/server/templates/floris_templates/main.html b/server/templates/floris_templates/main.html new file mode 100644 index 0000000..9bc3c4b --- /dev/null +++ b/server/templates/floris_templates/main.html @@ -0,0 +1,85 @@ + + + + + + Image Viewer + + + + + + +
+
+
+
+
+ + + + + + + + + + + {% for row in weather %} + + + + + + {% endfor %} + +
#Wind DirectionWind Speed
+ + {{ row.WindDir }}{{ row.WindSpeed }}
+
+
+
+
+ X + +
+
+ Y + +
+
+
+ +
+
+ {{ data }} + {% if data is defined %} + Selected Image + {% endif %} +
+
+ + + + + + + diff --git a/server/templates/main.html b/server/templates/main.html deleted file mode 100644 index 01e50b9..0000000 --- a/server/templates/main.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - Image Viewer - - - -
-
- Selected Image - - -
-
-

Available Images

-
    - {% for image in images %} -
  • {{ image }}
  • - {% endfor %} -
-
-
- - - -