infra-analyticsFastAPIapp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.4
2
+ Name: infra-analyticsFastAPIapp
3
+ Version: 0.1.0
4
+ Summary: Library for green infrastructure analysis
5
+ License: MIT
6
+ Author: ViolettaZim
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: fastapi (>=0.136.0,<0.137.0)
15
+ Requires-Dist: uvicorn (>=0.49.0,<0.50.0)
16
+ Description-Content-Type: text/markdown
17
+
18
+ # infra-analytics
19
+
20
+ Библиотека для анализа зелёных насаждений и доступности инфраструктуры в городской среде.
21
+
22
+ ## Установка
23
+
24
+ ```bash
25
+ pip install infra-analytics
@@ -0,0 +1,8 @@
1
+ # infra-analytics
2
+
3
+ Библиотека для анализа зелёных насаждений и доступности инфраструктуры в городской среде.
4
+
5
+ ## Установка
6
+
7
+ ```bash
8
+ pip install infra-analytics
@@ -0,0 +1,26 @@
1
+ from typing import Dict, Any, Optional
2
+ import requests
3
+
4
+
5
+ class BaseAPIClient:
6
+ def __init__(self, base_url: str):
7
+ self.base_url = base_url
8
+ self.session = requests.Session()
9
+
10
+ def get(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
11
+ """GET запрос к API."""
12
+ url = f"{self.base_url}/{endpoint.lstrip('/')}"
13
+ response = self.session.get(url, params=params)
14
+ response.raise_for_status()
15
+ return response.json()
16
+
17
+ def post(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
18
+ """POST запрос к API."""
19
+ url = f"{self.base_url}/{endpoint.lstrip('/')}"
20
+ response = self.session.post(url, json=data)
21
+ response.raise_for_status()
22
+ return response.json()
23
+
24
+ def close(self):
25
+ """Закрытие сессии."""
26
+ self.session.close()
File without changes
@@ -0,0 +1,27 @@
1
+ [tool.poetry]
2
+ name = "infra-analyticsFastAPIapp"
3
+ version = "0.1.0"
4
+ description = "Library for green infrastructure analysis"
5
+ authors = ["ViolettaZim"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ packages = [
9
+ { include = "common" },
10
+ { include = "routers" },
11
+ { include = "services" }
12
+ ]
13
+
14
+ [tool.poetry.dependencies]
15
+ python = "^3.11"
16
+ fastapi = "^0.136.0"
17
+ uvicorn = "^0.49.0"
18
+
19
+ [tool.poetry.group.dev.dependencies]
20
+ pytest = "^8.0.0"
21
+ black = "^24.0.0"
22
+ isort = "^5.13.0"
23
+ pre-commit = "^3.0.0"
24
+
25
+ [build-system]
26
+ requires = ["poetry-core"]
27
+ build-backend = "poetry.core.masonry.api"
File without changes
@@ -0,0 +1,66 @@
1
+ from fastapi import APIRouter, HTTPException, Query
2
+ from typing import Optional
3
+
4
+ from services.test_service import tree_service
5
+
6
+ tree_router = APIRouter(prefix="/trees", tags=["Trees"])
7
+
8
+ @tree_router.get("/health")
9
+ def health_check():
10
+ """Проверка работоспособности API."""
11
+ return {"status": "ok"}
12
+
13
+ @tree_router.get("/accessibility")
14
+ def tree_accessibility(
15
+ diameter: float = Query(..., description="Диаметр ствола дерева (см)"),
16
+ height: float = Query(..., description="Высота дерева (м)"),
17
+ radius: float = Query(500, description="Радиус доступности инфраструктуры (м)")
18
+ ):
19
+ """
20
+ Расчёт доступности инфраструктуры для дерева.
21
+ """
22
+ return tree_service.calculate_infrastructure_score(diameter, height, radius)
23
+
24
+ @tree_router.get("/growth-prediction")
25
+ def predict_growth(
26
+ current_diameter: float = Query(..., description="Текущий диаметр (см)"),
27
+ age: int = Query(..., description="Возраст дерева (лет)"),
28
+ location: str = Query("park", description="Тип локации (park/other)")
29
+ ):
30
+ """Прогнозирование роста дерева."""
31
+ return tree_service.predict_tree_growth(current_diameter, age, location)
32
+
33
+ @tree_router.get("/health-status")
34
+ def get_health_status(
35
+ diameter: float = Query(..., description="Диаметр ствола дерева (см)"),
36
+ height: float = Query(..., description="Высота дерева (м)"),
37
+ has_damage: bool = Query(False, description="Наличие повреждений")
38
+ ):
39
+ """Определение состояния здоровья дерева."""
40
+ return tree_service.get_health_status(diameter, height, has_damage)
41
+
42
+ @tree_router.get("/execute")
43
+ def execute_operation(
44
+ operation: str = Query(..., description="Операция: calculate_score, predict_growth, get_health_status"),
45
+ diameter: float = Query(..., description="Диаметр ствола дерева (см)"),
46
+ height: float = Query(..., description="Высота дерева (м)"),
47
+ radius: float = Query(500, description="Радиус доступности инфраструктуры (м)"),
48
+ current_diameter: Optional[float] = Query(None, description="Текущий диаметр для predict_growth"),
49
+ age: Optional[int] = Query(None, description="Возраст для predict_growth"),
50
+ location: Optional[str] = Query("park", description="Локация для predict_growth"),
51
+ has_damage: Optional[bool] = Query(False, description="Повреждения для get_health_status")
52
+ ):
53
+
54
+ try:
55
+ if operation == "calculate_score":
56
+ return tree_service.extract_operation(operation, diameter, height, radius)
57
+ elif operation == "predict_growth":
58
+ if current_diameter is None or age is None:
59
+ raise HTTPException(status_code=400, detail="Для predict_growth нужны current_diameter и age")
60
+ return tree_service.extract_operation(operation, current_diameter, age, location)
61
+ elif operation == "get_health_status":
62
+ return tree_service.extract_operation(operation, diameter, height, has_damage)
63
+ else:
64
+ raise HTTPException(status_code=400, detail=f"Операция {operation} не поддерживается")
65
+ except Exception as e:
66
+ raise HTTPException(status_code=500, detail=str(e))
@@ -0,0 +1 @@
1
+ from .test_service import TreeInfraService
@@ -0,0 +1,77 @@
1
+ from typing import Optional
2
+
3
+
4
+ class TreeInfraService:
5
+ def __init__(self, api_client=None):
6
+ self.operations = {
7
+ "calculate_score": self.calculate_infrastructure_score,
8
+ "predict_growth": self.predict_tree_growth,
9
+ "get_health_status": self.get_health_status
10
+ }
11
+
12
+ def extract_operation(self, operation: str, *args, **kwargs):
13
+ """Извлечение и выполнение операции."""
14
+ if operation not in self.operations:
15
+ raise Exception(f"Operation '{operation}' not available. Available: {list(self.operations.keys())}")
16
+ else:
17
+ return self.operations[operation](*args, **kwargs)
18
+
19
+ def calculate_infrastructure_score(self, diameter: float, height: float, radius: float = 500):
20
+ """
21
+ Расчёт доступности инфраструктуры для дерева.
22
+ """
23
+ if diameter > 30 and height > 10:
24
+ score = 0.8
25
+ elif diameter > 15:
26
+ score = 0.5
27
+ else:
28
+ score = 0.2
29
+ return {
30
+ "diameter_cm": diameter,
31
+ "height_m": height,
32
+ "radius_m": radius,
33
+ "infrastructure_score": score,
34
+ "status": "good" if score > 0.5 else "needs_improvement"
35
+ }
36
+
37
+ def predict_tree_growth(self, current_diameter: float, age: int, location: str = "park"):
38
+ """
39
+ Прогнозирование роста дерева.
40
+ """
41
+ growth_factor = 1.15 if location == "park" else 1.05
42
+ predicted = current_diameter * growth_factor * (1 + 0.02 * (10 - min(age, 10)))
43
+ return {
44
+ "current_diameter_cm": current_diameter,
45
+ "age_years": age,
46
+ "location_type": location,
47
+ "predicted_diameter_5years_cm": round(predicted, 2),
48
+ "growth_rate_percent": round((predicted - current_diameter) / current_diameter * 100, 2)
49
+ }
50
+
51
+ def get_health_status(self, diameter: float, height: float, has_damage: bool = False):
52
+ """
53
+ Определение состояния здоровья дерева.
54
+ """
55
+ if has_damage:
56
+ health_score = 0.3
57
+ status = "poor"
58
+ elif diameter > 30 and height > 10:
59
+ health_score = 0.9
60
+ status = "excellent"
61
+ elif diameter > 15:
62
+ health_score = 0.7
63
+ status = "good"
64
+ else:
65
+ health_score = 0.5
66
+ status = "fair"
67
+
68
+ return {
69
+ "diameter_cm": diameter,
70
+ "height_m": height,
71
+ "has_damage": has_damage,
72
+ "health_score": health_score,
73
+ "health_status": status
74
+ }
75
+
76
+
77
+ tree_service = TreeInfraService()