UPDATE
This commit is contained in:
@@ -0,0 +1,685 @@
|
||||
# مستند کامل عملکرد فعلی `location_data`
|
||||
|
||||
این فایل شرح میدهد که اپ `location_data` در وضعیت فعلی دقیقاً چه کاری انجام میدهد، چه مدلهایی دارد، جریان درخواستها چگونه است، منطق تقسیمبندی بلوکها چگونه اجرا میشود و چه بخشهایی فقط داده ذخیرهشده را برمیگردانند.
|
||||
|
||||
---
|
||||
|
||||
## 1) هدف فعلی اپ `location_data`
|
||||
|
||||
اپ `location_data` در وضعیت فعلی چند مسئولیت اصلی دارد:
|
||||
|
||||
- نگهداری موقعیت جغرافیایی زمین با `lat` و `lon`
|
||||
- نگهداری مرز زمین یا بلوک در `farm_boundary`
|
||||
- نگهداری ساختار بلوکهای اصلی زمین در `block_layout`
|
||||
- نگهداری نتیجه خردسازی هوشمند هر بلوک در مدل `BlockSubdivision`
|
||||
- تولید نقاط شبکهای 100 متری یا هر اندازهای که با `SUBDIVISION_CHUNK_SQM` تنظیم شود
|
||||
- اجرای خوشهبندی `KMeans` روی نقاط شبکهای
|
||||
- پیدا کردن تعداد بهینه خوشهها با روش `Elbow`
|
||||
- ذخیره centroidهای نهایی هر بخش خردشده
|
||||
- تولید و ذخیره تصویر نمودار `K-SSE` برای هر subdivision
|
||||
- نگهداری دادههای خاک در `SoilDepthData`
|
||||
- نگهداری دادههای NDVI در `NdviObservation`
|
||||
|
||||
نکته مهم:
|
||||
|
||||
- در فاز فعلی، `GET` هیچ پردازش جدیدی انجام نمیدهد.
|
||||
- تمام پردازش subdivision فقط در زمان `POST` و فقط اگر subdivision آن بلوک قبلاً ساخته نشده باشد اجرا میشود.
|
||||
|
||||
---
|
||||
|
||||
## 2) تنظیمات محیطی
|
||||
|
||||
### `SUBDIVISION_CHUNK_SQM`
|
||||
|
||||
در `config/settings.py` یک متغیر جدید اضافه شده است:
|
||||
|
||||
- `SUBDIVISION_CHUNK_SQM`
|
||||
- مقدار پیشفرض: `100`
|
||||
- واحد: متر مربع
|
||||
|
||||
کاربرد:
|
||||
|
||||
- تعیین میکند شبکه اولیه برای subdivision با چه اندازهای ساخته شود.
|
||||
- اگر مقدار `100` باشد، هر chunk تقریباً یک سلول `10m x 10m` خواهد بود، چون:
|
||||
|
||||
```text
|
||||
step = sqrt(100) = 10 meters
|
||||
```
|
||||
|
||||
این مقدار از `.env` یا environment خوانده میشود:
|
||||
|
||||
```env
|
||||
SUBDIVISION_CHUNK_SQM=100
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3) مدلهای اصلی اپ
|
||||
|
||||
## 3.1) `SoilLocation`
|
||||
|
||||
این مدل رکورد اصلی location را نگه میدارد.
|
||||
|
||||
### فیلدها
|
||||
|
||||
- `latitude`
|
||||
- `longitude`
|
||||
- `task_id`
|
||||
- `farm_boundary`
|
||||
- `input_block_count`
|
||||
- `block_layout`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
### نقش
|
||||
|
||||
- هر location با ترکیب `latitude + longitude` یکتا است.
|
||||
- اطلاعات کلی زمین یا مرکز زمین را نگه میدارد.
|
||||
- اگر هنوز هیچ تقسیمبندی انجام نشده باشد، ساختار اولیه بلوکها را در `block_layout` نگه میدارد.
|
||||
|
||||
### `block_layout`
|
||||
|
||||
این فیلد JSON ساختار بلوکها را نگه میدارد. نمونه ساده:
|
||||
|
||||
```json
|
||||
{
|
||||
"input_block_count": 1,
|
||||
"default_full_farm": true,
|
||||
"algorithm_status": "completed",
|
||||
"blocks": [
|
||||
{
|
||||
"block_code": "block-1",
|
||||
"order": 1,
|
||||
"source": "default",
|
||||
"needs_subdivision": true,
|
||||
"sub_blocks": [
|
||||
{
|
||||
"sub_block_code": "sub-block-1",
|
||||
"centroid_lat": 35.689123,
|
||||
"centroid_lon": 51.389456
|
||||
}
|
||||
],
|
||||
"subdivision_summary": {
|
||||
"chunk_size_sqm": 100,
|
||||
"grid_point_count": 24,
|
||||
"centroid_count": 3,
|
||||
"optimal_k": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### رفتار مهم
|
||||
|
||||
- اگر `block_layout` خالی باشد، به صورت پیشفرض با یک بلوک کامل ساخته میشود.
|
||||
- متد `set_input_block_count()` ساختار اولیه بلوکهای اصلی را میسازد.
|
||||
|
||||
---
|
||||
|
||||
## 3.2) `BlockSubdivision`
|
||||
|
||||
این مدل نتیجه واقعی subdivision برای هر بلوک را ذخیره میکند.
|
||||
|
||||
### فیلدها
|
||||
|
||||
- `soil_location`: ارتباط با `SoilLocation`
|
||||
- `block_code`: شناسه بلوکی که subdivision روی آن اجرا شده
|
||||
- `source_boundary`: مرز همان بلوک
|
||||
- `chunk_size_sqm`: اندازه هر chunk
|
||||
- `grid_points`: نقاط اولیه شبکه
|
||||
- `centroid_points`: centroidهای نهایی خوشهها
|
||||
- `grid_point_count`: تعداد نقاط اولیه
|
||||
- `centroid_count`: تعداد centroidهای نهایی
|
||||
- `elbow_plot`: تصویر نمودار elbow
|
||||
- `status`: وضعیت رکورد
|
||||
- `metadata`: داده تکمیلی مانند `optimal_k` و `inertia_curve`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
### نقش
|
||||
|
||||
این مدل منبع اصلی داده subdivision است.
|
||||
|
||||
یعنی:
|
||||
|
||||
- نقاط خام شبکه در این مدل ذخیره میشوند
|
||||
- centroidهای نهایی هم در این مدل ذخیره میشوند
|
||||
- نمودار elbow هم در همین مدل ذخیره میشود
|
||||
|
||||
### قید یکتا
|
||||
|
||||
برای هر location و هر `block_code` فقط یک subdivision وجود دارد:
|
||||
|
||||
```text
|
||||
(soil_location, block_code) unique
|
||||
```
|
||||
|
||||
بنابراین اگر برای یک بلوک قبلاً subdivision ساخته شده باشد، دوباره ایجاد نمیشود.
|
||||
|
||||
---
|
||||
|
||||
## 3.3) `SoilDepthData`
|
||||
|
||||
این مدل دادههای خاک برای عمقهای مختلف را نگه میدارد.
|
||||
|
||||
عمقهای فعلی:
|
||||
|
||||
- `0-5cm`
|
||||
- `5-15cm`
|
||||
- `15-30cm`
|
||||
|
||||
این بخش در حال حاضر مستقل از subdivision است و هنوز برای هر sub-block جداگانه داده خاک تولید نمیکند.
|
||||
|
||||
---
|
||||
|
||||
## 3.4) `NdviObservation`
|
||||
|
||||
این مدل دادههای NDVI و سلامت پوشش گیاهی را نگه میدارد.
|
||||
|
||||
این بخش هم فعلاً مستقل از منطق subdivision است.
|
||||
|
||||
---
|
||||
|
||||
## 4) فایل `block_subdivision.py`
|
||||
|
||||
فایل `location_data/block_subdivision.py` مرکز اصلی منطق هوشمند subdivision است.
|
||||
|
||||
### وظایف اصلی این فایل
|
||||
|
||||
- استخراج polygon از ورودی
|
||||
- تبدیل مختصات جغرافیایی به صفحه محلی متری
|
||||
- ساخت grid points با اندازه chunk مشخص
|
||||
- اجرای `KMeans` برای `K=1..10`
|
||||
- ذخیره `SSE` یا همان `Inertia`
|
||||
- پیدا کردن elbow point
|
||||
- ساخت centroidهای نهایی خوشهها
|
||||
- sync کردن نتیجه با `block_layout`
|
||||
- تولید تصویر نمودار elbow
|
||||
- ذخیره تصویر در مدل با `ContentFile`
|
||||
|
||||
---
|
||||
|
||||
## 5) روند هندسی subdivision
|
||||
|
||||
## 5.1) استخراج Polygon
|
||||
|
||||
ورودی boundary میتواند به چند شکل بیاید:
|
||||
|
||||
- GeoJSON Polygon
|
||||
- `corners`
|
||||
- آرایه مستقیم از نقاط
|
||||
|
||||
تابع `extract_polygon()` این ورودی را به لیستی از نقاط جغرافیایی تبدیل میکند.
|
||||
|
||||
نمونه ورودی معتبر:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[51.3890, 35.6890],
|
||||
[51.3902, 35.6890],
|
||||
[51.3902, 35.6900],
|
||||
[51.3890, 35.6900],
|
||||
[51.3890, 35.6890]
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5.2) تبدیل مختصات به فضای محلی متری
|
||||
|
||||
برای اینکه بتوانیم فاصلهها و گریدبندی را بر اساس متر حساب کنیم، polygon از مختصات جغرافیایی به مختصات محلی متری تبدیل میشود.
|
||||
|
||||
تابع مربوط:
|
||||
|
||||
- `project_polygon_to_local_meters()`
|
||||
|
||||
ویژگی این تبدیل:
|
||||
|
||||
- نقطه اول polygon به عنوان origin در نظر گرفته میشود
|
||||
- با تقریب محلی، `lat/lon` به `x/y` در واحد متر تبدیل میشوند
|
||||
|
||||
این تبدیل برای subdivision کوچک و محلی مناسب است.
|
||||
|
||||
---
|
||||
|
||||
## 5.3) تولید grid points
|
||||
|
||||
تابع:
|
||||
|
||||
- `generate_grid_points()`
|
||||
|
||||
منطق:
|
||||
|
||||
1. ابتدا اندازه گام محاسبه میشود:
|
||||
|
||||
```text
|
||||
step_m = sqrt(chunk_size_sqm)
|
||||
```
|
||||
|
||||
2. روی bounding box polygon، نقاط مرکزی grid بررسی میشوند.
|
||||
3. هر نقطهای که داخل polygon باشد نگه داشته میشود.
|
||||
|
||||
خروجی:
|
||||
|
||||
- `grid_points`: مختصات جغرافیایی قابل ذخیره در JSON
|
||||
- `grid_vectors`: مختصات محلی متری برای ورود به `KMeans`
|
||||
|
||||
نمونه هر grid point:
|
||||
|
||||
```json
|
||||
{
|
||||
"point_code": "pt-1",
|
||||
"lat": 35.689123,
|
||||
"lon": 51.389456
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6) الگوریتم خوشهبندی هوشمند
|
||||
|
||||
## 6.1) اجرای `KMeans`
|
||||
|
||||
تابع:
|
||||
|
||||
- `cluster_grid_points()`
|
||||
|
||||
منطق:
|
||||
|
||||
- روی `grid_vectors` خوشهبندی انجام میشود
|
||||
- برای `K=1` تا `K=10` اجرا میشود
|
||||
- اگر تعداد نقاط کمتر از 10 باشد، `max_k = len(grid_vectors)` در نظر گرفته میشود
|
||||
|
||||
برای هر `K`:
|
||||
|
||||
- مدل `KMeans` ساخته میشود
|
||||
- `fit()` اجرا میشود
|
||||
- مقدار `model.inertia_` به عنوان `SSE` ذخیره میشود
|
||||
|
||||
خروجی میانی:
|
||||
|
||||
```json
|
||||
[
|
||||
{"k": 1, "sse": 1300.5},
|
||||
{"k": 2, "sse": 640.2},
|
||||
{"k": 3, "sse": 390.1}
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6.2) پیدا کردن Elbow Point
|
||||
|
||||
تابع:
|
||||
|
||||
- `detect_elbow_point()`
|
||||
|
||||
منطق فعلی:
|
||||
|
||||
1. از روی SSEها، شیب افت بین نقاط متوالی محاسبه میشود.
|
||||
2. سپس تغییرات شیب محاسبه میشود.
|
||||
3. هر جایی که افت شیب ناگهان متوقف شود، همان نقطه elbow در نظر گرفته میشود.
|
||||
|
||||
یعنی در عمل:
|
||||
|
||||
- ابتدا `slopes` محاسبه میشود
|
||||
- سپس اختلاف شیبها بررسی میشود
|
||||
- بیشترین تغییر شیب به عنوان elbow انتخاب میشود
|
||||
|
||||
خروجی:
|
||||
|
||||
- `optimal_k`
|
||||
|
||||
---
|
||||
|
||||
## 6.3) تولید centroidهای نهایی
|
||||
|
||||
بعد از پیدا شدن `optimal_k`:
|
||||
|
||||
- مدل `KMeans` همان `K` نهایی انتخاب میشود
|
||||
- مختصات مراکز خوشهها (`cluster_centers_`) گرفته میشود
|
||||
- از فضای متری به `lat/lon` تبدیل میشود
|
||||
- در `centroid_points` ذخیره میشود
|
||||
|
||||
نمونه centroid:
|
||||
|
||||
```json
|
||||
{
|
||||
"sub_block_code": "sub-block-1",
|
||||
"centroid_lat": 35.689321,
|
||||
"centroid_lon": 51.389789
|
||||
}
|
||||
```
|
||||
|
||||
این centroidها در عمل همان مراکز بخشهای کوچکتر زمین هستند.
|
||||
|
||||
---
|
||||
|
||||
## 7) تولید و ذخیره نمودار Elbow
|
||||
|
||||
### تابع
|
||||
|
||||
- `render_elbow_plot()`
|
||||
|
||||
### منطق
|
||||
|
||||
پس از محاسبه `inertia_curve` و `optimal_k`:
|
||||
|
||||
1. نمودار `K` در برابر `SSE` رسم میشود
|
||||
2. نقطه elbow با رنگ قرمز مشخص میشود
|
||||
3. تصویر به صورت PNG در `BytesIO` ذخیره میشود
|
||||
4. با `ContentFile` به `ImageField` مدل `BlockSubdivision` داده میشود
|
||||
|
||||
### نکته مهم حافظه
|
||||
|
||||
برای جلوگیری از memory leak:
|
||||
|
||||
- از backend غیرتعاملی `Agg` استفاده میشود
|
||||
- بعد از ذخیره تصویر، `plt.close(fig)` اجرا میشود
|
||||
- buffer هم بسته میشود
|
||||
|
||||
این برای پردازشهای همزمان سرور ضروری است.
|
||||
|
||||
---
|
||||
|
||||
## 8) جریان کامل `POST /api/soil-data/`
|
||||
|
||||
این endpoint الان مهمترین ورودی subdivision است.
|
||||
|
||||
### ورودیهای قابل پشتیبانی
|
||||
|
||||
- `lat`
|
||||
- `lon`
|
||||
- `block_count`
|
||||
- `block_code`
|
||||
- `farm_boundary`
|
||||
|
||||
### سناریوی اجرا
|
||||
|
||||
#### مرحله 1: اعتبارسنجی ورودی
|
||||
|
||||
سریالایزر `SoilDataRequestSerializer` داده را validate میکند.
|
||||
|
||||
#### مرحله 2: پیدا کردن یا ساخت location
|
||||
|
||||
بر اساس `lat/lon`:
|
||||
|
||||
- اگر location وجود نداشته باشد ساخته میشود
|
||||
- اگر وجود داشته باشد از همان رکورد استفاده میشود
|
||||
|
||||
#### مرحله 3: آپدیت ساختار اولیه بلوکها
|
||||
|
||||
اگر `block_count` فرق کرده باشد:
|
||||
|
||||
- `block_layout` دوباره با `set_input_block_count()` ساخته میشود
|
||||
|
||||
#### مرحله 4: انتخاب boundary برای subdivision
|
||||
|
||||
اولویت:
|
||||
|
||||
1. `farm_boundary` ارسالی در request
|
||||
2. اگر نبود، `location.farm_boundary` ذخیرهشده
|
||||
|
||||
#### مرحله 5: اجرای subdivision فقط در صورت نیاز
|
||||
|
||||
تابع:
|
||||
|
||||
- `create_or_get_block_subdivision()`
|
||||
|
||||
اگر رکورد `(location, block_code)` از قبل وجود داشته باشد:
|
||||
|
||||
- هیچ پردازش جدیدی اجرا نمیشود
|
||||
- همان رکورد قبلی برگردانده میشود
|
||||
|
||||
اگر وجود نداشته باشد:
|
||||
|
||||
- grid ساخته میشود
|
||||
- KMeans اجرا میشود
|
||||
- elbow پیدا میشود
|
||||
- centroidها ساخته میشوند
|
||||
- نمودار elbow ساخته میشود
|
||||
- همه چیز در `BlockSubdivision` ذخیره میشود
|
||||
- `block_layout` با `sub_blocks` sync میشود
|
||||
|
||||
#### مرحله 6: response
|
||||
|
||||
خروجی شامل اینهاست:
|
||||
|
||||
- اطلاعات `SoilLocation`
|
||||
- `farm_boundary`
|
||||
- `block_layout`
|
||||
- `block_subdivisions`
|
||||
- `depths`
|
||||
|
||||
فیلد `source` در response:
|
||||
|
||||
- `created` اگر location یا subdivision جدید ساخته شده باشد
|
||||
- `database` اگر قبلاً وجود داشته باشد
|
||||
|
||||
---
|
||||
|
||||
## 9) جریان کامل `GET /api/soil-data/`
|
||||
|
||||
این endpoint الان فقط برای read استفاده میشود.
|
||||
|
||||
### ورودی
|
||||
|
||||
- `lat`
|
||||
- `lon`
|
||||
- `block_code` اختیاری
|
||||
|
||||
### رفتار
|
||||
|
||||
- location را از دیتابیس پیدا میکند
|
||||
- subdivisionهای ذخیرهشده را میخواند
|
||||
- هیچ الگوریتمی را اجرا نمیکند
|
||||
- هیچ `KMeans` یا پردازش هندسی انجام نمیدهد
|
||||
|
||||
### پاسخ
|
||||
|
||||
داده ذخیرهشده را با `source = database` برمیگرداند.
|
||||
|
||||
اگر location پیدا نشود:
|
||||
|
||||
- `404`
|
||||
|
||||
---
|
||||
|
||||
## 10) نقش `serializers.py`
|
||||
|
||||
### `SoilDataRequestSerializer`
|
||||
|
||||
ورودی endpoint اصلی را مدیریت میکند:
|
||||
|
||||
- `lat`
|
||||
- `lon`
|
||||
- `block_count`
|
||||
- `block_code`
|
||||
- `farm_boundary`
|
||||
|
||||
### `SoilLocationResponseSerializer`
|
||||
|
||||
خروجی location را برمیگرداند:
|
||||
|
||||
- `id`
|
||||
- `lat`
|
||||
- `lon`
|
||||
- `input_block_count`
|
||||
- `farm_boundary`
|
||||
- `block_layout`
|
||||
- `block_subdivisions`
|
||||
- `depths`
|
||||
|
||||
### `BlockSubdivisionSerializer`
|
||||
|
||||
خروجی subdivision را برمیگرداند:
|
||||
|
||||
- `block_code`
|
||||
- `chunk_size_sqm`
|
||||
- `grid_points`
|
||||
- `centroid_points`
|
||||
- `grid_point_count`
|
||||
- `centroid_count`
|
||||
- `elbow_plot`
|
||||
- `status`
|
||||
- `metadata`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
---
|
||||
|
||||
## 11) نقش `block_layout` در کنار `BlockSubdivision`
|
||||
|
||||
در معماری فعلی دو سطح ذخیرهسازی داریم:
|
||||
|
||||
### 11.1) `BlockSubdivision`
|
||||
|
||||
منبع اصلی و canonical برای subdivision
|
||||
|
||||
### 11.2) `block_layout`
|
||||
|
||||
خلاصهای از نتیجه subdivision برای مصرف سریعتر در response و ساختار کلی location
|
||||
|
||||
یعنی:
|
||||
|
||||
- داده دقیق در `BlockSubdivision` است
|
||||
- خلاصه آن در `block_layout.blocks[].sub_blocks` قرار میگیرد
|
||||
|
||||
---
|
||||
|
||||
## 12) وضعیت فعلی بخشهای قدیمیتر اپ
|
||||
|
||||
## 12.1) `tasks.py`
|
||||
|
||||
این فایل هنوز وجود دارد و برای fetch داده خاک به صورت قدیمی استفاده میشود، اما در مسیر subdivision فعلی نقشی ندارد.
|
||||
|
||||
## 12.2) `soil_adapters.py`
|
||||
|
||||
این فایل adapterهای داده خاک را نگه میدارد و فعلاً برای subdivision استفاده نمیشود.
|
||||
|
||||
## 12.3) `remote_sensing.py`
|
||||
|
||||
منطق سنجشازدور را نگه میدارد و هنوز مستقیماً به subdivision وصل نشده است.
|
||||
|
||||
## 12.4) `ndvi.py`
|
||||
|
||||
برای endpoint مربوط به NDVI استفاده میشود و فعلاً از centroidهای subdivision استفاده نمیکند.
|
||||
|
||||
---
|
||||
|
||||
## 13) وابستگیهای جدید
|
||||
|
||||
برای عملکرد فعلی subdivision این dependencyها لازم هستند:
|
||||
|
||||
- `scikit-learn`
|
||||
- `matplotlib`
|
||||
- `Pillow`
|
||||
- `numpy`
|
||||
|
||||
### دلیل هرکدام
|
||||
|
||||
- `scikit-learn`: اجرای `KMeans`
|
||||
- `matplotlib`: رسم elbow plot
|
||||
- `Pillow`: پشتیبانی از `ImageField`
|
||||
- `numpy`: وابستگی پایه `scikit-learn`
|
||||
|
||||
---
|
||||
|
||||
## 14) migrationهای مهم مرتبط با ساختار فعلی
|
||||
|
||||
- `0008_soillocation_block_layout.py`
|
||||
- اضافه شدن `input_block_count`
|
||||
- اضافه شدن `block_layout`
|
||||
|
||||
- `0009_blocksubdivision.py`
|
||||
- اضافه شدن مدل `BlockSubdivision`
|
||||
|
||||
- `0010_blocksubdivision_elbow_plot.py`
|
||||
- اضافه شدن فیلد `elbow_plot`
|
||||
|
||||
---
|
||||
|
||||
## 15) محدودیتهای فعلی
|
||||
|
||||
چند محدودیت مهم در پیادهسازی فعلی وجود دارد:
|
||||
|
||||
- subdivision فعلاً بر اساس هندسه و خوشهبندی نقاط انجام میشود، نه بر اساس داده واقعی خاک یا NDVI
|
||||
- برای هر `block_code` فرض میشود یک مرز مستقل از بیرون داده میشود
|
||||
- هنوز برای هر `sub_block` رکورد location مستقل ساخته نمیشود
|
||||
- هنوز داده خاک، هوا و NDVI برای centroidهای جدید به صورت جداگانه fetch نمیشود
|
||||
- elbow detection فعلی heuristic-based است و هنوز نسخه پیشرفتهتر آماری ندارد
|
||||
|
||||
---
|
||||
|
||||
## 16) تستهای مرتبط
|
||||
|
||||
### `location_data/test_block_subdivision.py`
|
||||
|
||||
این تستها بررسی میکنند:
|
||||
|
||||
- elbow detection کار میکند
|
||||
- payload subdivision ساخته میشود
|
||||
- grid points و centroid points خروجی دارند
|
||||
|
||||
### `location_data/test_soil_api.py`
|
||||
|
||||
این تستها بررسی میکنند:
|
||||
|
||||
- `POST` subdivision جدید میسازد
|
||||
- `GET` فقط داده ذخیرهشده را برمیگرداند
|
||||
- الگوریتم در `GET` دوباره اجرا نمیشود
|
||||
|
||||
---
|
||||
|
||||
## 17) جمعبندی معماری فعلی
|
||||
|
||||
در وضعیت فعلی، `location_data` این معماری را دارد:
|
||||
|
||||
### لایه 1: Location پایه
|
||||
|
||||
- `SoilLocation`
|
||||
- `farm_boundary`
|
||||
- `block_layout`
|
||||
|
||||
### لایه 2: Subdivision هوشمند
|
||||
|
||||
- `BlockSubdivision`
|
||||
- grid generation
|
||||
- KMeans
|
||||
- elbow detection
|
||||
- centroid generation
|
||||
- elbow plot generation
|
||||
|
||||
### لایه 3: دادههای مکمل
|
||||
|
||||
- `SoilDepthData`
|
||||
- `NdviObservation`
|
||||
- بخشهای legacy مثل `tasks.py`
|
||||
|
||||
در نتیجه، اپ الان میتواند:
|
||||
|
||||
- یک بلوک با مرز مشخص بگیرد
|
||||
- آن را به نقاط شبکهای خرد کند
|
||||
- تعداد بهینه بخشها را با KMeans + Elbow پیدا کند
|
||||
- centroidهای نهایی را ذخیره کند
|
||||
- نمودار elbow را ذخیره کند
|
||||
- و در درخواستهای بعدی فقط همان نتیجه ذخیرهشده را بدون پردازش مجدد برگرداند
|
||||
|
||||
---
|
||||
|
||||
## 18) پیشنهاد برای مراحل بعدی
|
||||
|
||||
اگر در مرحله بعد بخواهی این ساختار را توسعه بدهی، منطقیترین قدمها اینها هستند:
|
||||
|
||||
1. ساخت endpoint مستقل برای subdivision هر block
|
||||
2. اتصال هر centroid به fetch داده خاک و هوا
|
||||
3. ساخت رکورد مستقل برای هر `sub_block`
|
||||
4. استفاده از NDVI یا داده سنسور برای تعیین `K` یا وزندهی خوشهها
|
||||
5. نمایش مستقیم `elbow_plot` با URL کامل media
|
||||
|
||||
Reference in New Issue
Block a user