Files
Ai/scripts/generate_mock_data.py
T
2026-04-25 17:22:41 +03:30

799 lines
23 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parents[1]
MOCK_DIR = BASE_DIR / "json" / "mock_data"
def queue_response(message, task_id, status_url, **extra):
data = {
"task_id": task_id,
"status_url": status_url,
}
data.update(extra)
return {
"code": 202,
"msg": message,
"data": data,
}
def ok_response(data, message="success", code=200):
return {
"code": code,
"msg": message,
"data": data,
}
def error_response(code, message, data=None):
return {
"code": code,
"msg": message,
"data": data,
}
def task_pending(task_id):
return ok_response(
{
"task_id": task_id,
"status": "PENDING",
"message": "تسک در صف یا یافت نشد.",
}
)
def task_progress(task_id, progress):
return ok_response(
{
"task_id": task_id,
"status": "PROGRESS",
"progress": progress,
}
)
def task_success(task_id, result):
return ok_response(
{
"task_id": task_id,
"status": "SUCCESS",
"result": result,
}
)
def task_failure(task_id, error):
return ok_response(
{
"task_id": task_id,
"status": "FAILURE",
"error": error,
}
)
PLANT = {
"id": 1,
"name": "گوجه‌فرنگی",
"light": "آفتاب کامل",
"watering": "منظم، هفته‌ای ۲ تا ۳ بار",
"soil": "لومی، غنی از مواد آلی",
"temperature": "۲۰ تا ۳۰ درجه سانتی‌گراد",
"planting_season": "بهار",
"harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
"spacing": "۴۵ تا ۶۰ سانتی‌متر",
"fertilizer": "کود NPK متعادل",
"created_at": "2025-03-20T10:00:00Z",
"updated_at": "2025-03-24T10:00:00Z",
}
IRRIGATION_METHOD = {
"id": 1,
"name": "آبیاری قطره‌ای",
"category": "موضعی",
"description": "آبیاری با دبی کم و راندمان بالا",
"water_efficiency_percent": 90.0,
"water_pressure_required": "۱-۲ اتمسفر",
"flow_rate": "۲-۸ لیتر در ساعت",
"coverage_area": "بسته به طراحی سیستم",
"soil_type": "اکثر خاک‌ها",
"climate_suitability": "گرم و خشک",
"created_at": "2025-03-20T10:00:00Z",
"updated_at": "2025-03-24T10:00:00Z",
}
SOIL_DEPTHS = [
{
"depth_label": "0-5cm",
"bdod": 1.31,
"cec": 18.4,
"cfvo": 2.0,
"clay": 24.0,
"nitrogen": 0.18,
"ocd": 32.0,
"ocs": 4.1,
"phh2o": 7.2,
"sand": 34.0,
"silt": 42.0,
"soc": 1.6,
"wv0010": 0.31,
"wv0033": 0.22,
"wv1500": 0.11,
},
{
"depth_label": "5-15cm",
"bdod": 1.35,
"cec": 17.2,
"cfvo": 2.3,
"clay": 26.0,
"nitrogen": 0.16,
"ocd": 28.0,
"ocs": 3.7,
"phh2o": 7.1,
"sand": 36.0,
"silt": 38.0,
"soc": 1.4,
"wv0010": 0.29,
"wv0033": 0.2,
"wv1500": 0.1,
},
{
"depth_label": "15-30cm",
"bdod": 1.39,
"cec": 15.8,
"cfvo": 2.8,
"clay": 28.0,
"nitrogen": 0.13,
"ocd": 22.0,
"ocs": 3.2,
"phh2o": 7.0,
"sand": 38.0,
"silt": 34.0,
"soc": 1.1,
"wv0010": 0.26,
"wv0033": 0.18,
"wv1500": 0.09,
},
]
SOIL_LOCATION = {
"source": "database",
"id": 12,
"lon": "51.389000",
"lat": "35.689200",
"depths": SOIL_DEPTHS,
}
SOIL_TASK_DATA = {
"source": "task",
"task_id": "soil-task-123",
"lon": 51.389,
"lat": 35.6892,
"status_url": "/api/soil-data/tasks/soil-task-123/status/",
}
SENSOR_DATA = {
"farm_uuid": "550e8400-e29b-41d4-a716-446655440000",
"center_location_id": 12,
"weather_forecast_id": 21,
"sensor_payload": {
"sensor-7-1": {
"soil_moisture": 45.2,
"soil_temperature": 22.5,
"soil_ph": 6.8,
"electrical_conductivity": 1.2,
"nitrogen": 30.0,
"phosphorus": 15.0,
"potassium": 20.0,
}
},
"plant_ids": [1],
"created_at": "2025-03-20T10:00:00Z",
"updated_at": "2025-03-24T10:00:00Z",
}
SENSOR_PARAMETER = {
"id": 3,
"sensor_key": "sensor-7-1",
"code": "soil_moisture",
"name_fa": "رطوبت خاک",
"unit": "%",
"data_type": "float",
"metadata": {"min": 0, "max": 100},
"created_at": "2025-03-24T10:00:00Z",
"action": "added",
}
IRRIGATION_RECOMMENDATION_RESULT = {
"plan": {
"frequencyPerWeek": 3,
"durationMinutes": 42,
"bestTimeOfDay": "صبح زود",
"moistureLevel": 68,
"warning": "در صورت بارش موثر، نوبت سوم این هفته را حذف کنید.",
},
"raw_response": "{\"plan\":{\"frequencyPerWeek\":3,\"durationMinutes\":42}}",
"water_balance": {
"daily": [
{
"forecast_date": "2025-03-25",
"et0_mm": 4.7,
"etc_mm": 5.6,
"effective_rainfall_mm": 0.0,
"gross_irrigation_mm": 6.2,
"irrigation_timing": "06:00-08:00",
}
],
"crop_profile": {
"kc_initial": 0.6,
"kc_mid": 1.15,
"kc_end": 0.8,
},
"active_kc": 1.15,
},
"status": "completed",
}
FERTILIZATION_RECOMMENDATION_RESULT = {
"plan": {
"npkRatio": "20-20-20",
"amountPerHectare": "150 kg/ha",
"applicationMethod": "کودآبیاری در دو نوبت",
"applicationInterval": "هر ۱۰ روز",
"reasoning": "نیتروژن و پتاسیم خاک در محدوده متوسط است و گیاه در فاز رویشی نیاز تغذیه‌ای بالاتری دارد.",
},
"raw_response": "{\"plan\":{\"npkRatio\":\"20-20-20\"}}",
"status": "completed",
}
DASHBOARD_RESULT = {
"sensor_id": "550e8400-e29b-41d4-a716-446655440000",
"all_cards": {
"farmOverviewKpis": {
"healthScore": 82,
"activeAlerts": 2,
"waterNeedMm": 18.4,
},
},
}
TASK_PROGRESS = {"current": 1, "total": 3, "message": "در حال پردازش..."}
RAG_STREAM_SUCCESS = {
"content_type": "text/plain; charset=utf-8",
"body": "سلام، برای بازیابی رطوبت خاک بهتر است آبیاری صبح‌گاهی را تنظیم کنید.",
}
index = []
def register(path, method, api_path, status_code, description, payload):
full_path = MOCK_DIR / path
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.write_text(
json.dumps(payload, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
index.append(
{
"method": method,
"path": api_path,
"status_code": status_code,
"description": description,
"file": str(Path("json/mock_data") / path),
}
)
def main():
register(
"dashboard-data/generate/post_202.json",
"POST",
"/api/dashboard-data/generate/",
202,
"Dashboard data task queued",
queue_response(
"dashboard task queued",
"dashboard-task-123",
"/api/dashboard-data/dashboard-task-123/status/",
),
)
register(
"dashboard-data/generate/post_400.json",
"POST",
"/api/dashboard-data/generate/",
400,
"Missing sensor_id",
error_response(400, "پارامتر sensor_id الزامی است.", None),
)
register(
"dashboard-data/status/get_200_pending.json",
"GET",
"/api/dashboard-data/{task_id}/status/",
200,
"Pending dashboard task",
task_pending("dashboard-task-123"),
)
register(
"dashboard-data/status/get_200_progress.json",
"GET",
"/api/dashboard-data/{task_id}/status/",
200,
"Dashboard task in progress",
task_progress(
"dashboard-task-123",
{"current": 5, "total": 15, "card": "sensorComparisonChart", "message": "processing sensorComparisonChart"},
),
)
register(
"dashboard-data/status/get_200_success.json",
"GET",
"/api/dashboard-data/{task_id}/status/",
200,
"Successful dashboard task",
task_success("dashboard-task-123", DASHBOARD_RESULT),
)
register(
"dashboard-data/status/get_200_failure.json",
"GET",
"/api/dashboard-data/{task_id}/status/",
200,
"Failed dashboard task",
task_failure("dashboard-task-123", "خطا در ساخت کارت‌های داشبورد."),
)
register(
"fertilization/recommend/post_202.json",
"POST",
"/api/fertilization/recommend/",
202,
"Fertilization task queued",
queue_response(
"تسک توصیه کودهی در صف قرار گرفت.",
"fert-task-123",
"/api/fertilization/recommend/fert-task-123/status/",
),
)
register(
"fertilization/recommend/post_400.json",
"POST",
"/api/fertilization/recommend/",
400,
"Validation error",
error_response(400, "داده نامعتبر.", {"sensor_uuid": ["This field is required."]}),
)
for name, payload in {
"pending": task_pending("fert-task-123"),
"progress": task_progress("fert-task-123", {"message": "در حال پردازش توصیه کودهی..."}),
"success": task_success("fert-task-123", FERTILIZATION_RECOMMENDATION_RESULT),
"failure": task_failure("fert-task-123", "خطا در دریافت توصیه کودهی."),
}.items():
register(
f"fertilization/status/get_200_{name}.json",
"GET",
"/api/fertilization/recommend/{task_id}/status/",
200,
f"Fertilization status {name}",
payload,
)
register(
"irrigation/methods/get_200.json",
"GET",
"/api/irrigation/",
200,
"List irrigation methods",
ok_response([IRRIGATION_METHOD]),
)
register(
"irrigation/methods/post_201.json",
"POST",
"/api/irrigation/",
201,
"Create irrigation method",
ok_response(IRRIGATION_METHOD, code=201),
)
register(
"irrigation/methods/post_400.json",
"POST",
"/api/irrigation/",
400,
"Irrigation create validation error",
error_response(400, "داده نامعتبر.", {"name": ["This field is required."]}),
)
register(
"irrigation/recommend/post_202.json",
"POST",
"/api/irrigation/recommend/",
202,
"Irrigation recommendation task queued",
queue_response(
"تسک توصیه آبیاری در صف قرار گرفت.",
"irr-task-123",
"/api/irrigation/recommend/irr-task-123/status/",
),
)
register(
"irrigation/recommend/post_400.json",
"POST",
"/api/irrigation/recommend/",
400,
"Irrigation recommendation validation error",
error_response(400, "داده نامعتبر.", {"sensor_uuid": ["This field is required."]}),
)
for name, payload in {
"pending": task_pending("irr-task-123"),
"progress": task_progress("irr-task-123", {"message": "در حال پردازش توصیه آبیاری..."}),
"success": task_success("irr-task-123", IRRIGATION_RECOMMENDATION_RESULT),
"failure": task_failure("irr-task-123", "خطا در دریافت توصیه آبیاری."),
}.items():
register(
f"irrigation/recommend/status/get_200_{name}.json",
"GET",
"/api/irrigation/recommend/{task_id}/status/",
200,
f"Irrigation recommendation status {name}",
payload,
)
for method, success_code in (("get", 200), ("put", 200), ("patch", 200)):
register(
f"irrigation/method-detail/{method}_{success_code}.json",
method.upper(),
"/api/irrigation/{pk}/",
success_code,
f"Irrigation method {method} success",
ok_response(IRRIGATION_METHOD, code=success_code),
)
if method in {"put", "patch"}:
register(
f"irrigation/method-detail/{method}_400.json",
method.upper(),
"/api/irrigation/{pk}/",
400,
f"Irrigation method {method} validation error",
error_response(400, "داده نامعتبر.", {"name": ["This field may not be blank."]}),
)
register(
f"irrigation/method-detail/{method}_404.json",
method.upper(),
"/api/irrigation/{pk}/",
404,
f"Irrigation method {method} not found",
error_response(404, "روش آبیاری یافت نشد.", None),
)
register(
"irrigation/method-detail/delete_200.json",
"DELETE",
"/api/irrigation/{pk}/",
200,
"Delete irrigation method",
error_response(200, "روش آبیاری با موفقیت حذف شد.", None),
)
register(
"irrigation/method-detail/delete_404.json",
"DELETE",
"/api/irrigation/{pk}/",
404,
"Delete irrigation method not found",
error_response(404, "روش آبیاری یافت نشد.", None),
)
register(
"soil-data/get_200_database.json",
"GET",
"/api/soil-data/",
200,
"Soil data served from database",
ok_response(SOIL_LOCATION),
)
register(
"soil-data/get_202_queued.json",
"GET",
"/api/soil-data/",
202,
"Soil data fetch task queued",
{
"code": 202,
"msg": "تسک در صف. وضعیت را با task_id بررسی کنید.",
"data": SOIL_TASK_DATA,
},
)
register(
"soil-data/get_400.json",
"GET",
"/api/soil-data/",
400,
"Soil data validation error",
error_response(400, "داده نامعتبر.", {"lat": ["This field is required."], "lon": ["This field is required."]}),
)
register(
"soil-data/post_200_database.json",
"POST",
"/api/soil-data/",
200,
"Soil data POST served from database",
ok_response(SOIL_LOCATION),
)
register(
"soil-data/post_202_queued.json",
"POST",
"/api/soil-data/",
202,
"Soil data POST task queued",
{
"code": 202,
"msg": "تسک در صف. وضعیت را با task_id بررسی کنید.",
"data": SOIL_TASK_DATA,
},
)
register(
"soil-data/post_400.json",
"POST",
"/api/soil-data/",
400,
"Soil data POST validation error",
error_response(400, "داده نامعتبر.", {"lat": ["A valid number is required."]}),
)
for name, payload in {
"pending": task_pending("soil-task-123"),
"progress": task_progress("soil-task-123", {"step": "fetch", "percent": 60}),
"success": task_success("soil-task-123", SOIL_LOCATION | {"source": "database"}),
"failure": task_failure("soil-task-123", "خطا در واکشی داده خاک."),
}.items():
register(
f"soil-data/status/get_200_{name}.json",
"GET",
"/api/soil-data/tasks/{task_id}/status/",
200,
f"Soil task status {name}",
payload,
)
register(
"plant/list-get_200.json",
"GET",
"/api/plants/",
200,
"List plants",
ok_response([PLANT]),
)
register(
"plant/create-post_201.json",
"POST",
"/api/plants/",
201,
"Create plant",
ok_response(PLANT, code=201),
)
register(
"plant/create-post_400.json",
"POST",
"/api/plants/",
400,
"Plant create validation error",
error_response(400, "داده نامعتبر.", {"name": ["This field is required."]}),
)
for method in ("get", "put", "patch"):
register(
f"plant/detail-{method}_200.json",
method.upper(),
"/api/plants/{pk}/",
200,
f"Plant detail {method} success",
ok_response(PLANT),
)
if method in {"put", "patch"}:
register(
f"plant/detail-{method}_400.json",
method.upper(),
"/api/plants/{pk}/",
400,
f"Plant detail {method} validation error",
error_response(400, "داده نامعتبر.", {"name": ["This field may not be blank."]}),
)
register(
f"plant/detail-{method}_404.json",
method.upper(),
"/api/plants/{pk}/",
404,
f"Plant detail {method} not found",
error_response(404, "گیاه یافت نشد.", None),
)
register(
"plant/detail-delete_200.json",
"DELETE",
"/api/plants/{pk}/",
200,
"Delete plant success",
error_response(200, "گیاه با موفقیت حذف شد.", None),
)
register(
"plant/detail-delete_404.json",
"DELETE",
"/api/plants/{pk}/",
404,
"Delete plant not found",
error_response(404, "گیاه یافت نشد.", None),
)
register(
"plant/fetch-info-post_200.json",
"POST",
"/api/plants/fetch-info/",
200,
"Fetch plant info success",
ok_response(PLANT),
)
register(
"plant/fetch-info-post_400.json",
"POST",
"/api/plants/fetch-info/",
400,
"Fetch plant info missing name",
error_response(400, "نام گیاه الزامی است.", None),
)
register(
"plant/fetch-info-post_503.json",
"POST",
"/api/plants/fetch-info/",
503,
"Fetch plant info service unavailable",
error_response(503, "سرویس API هنوز پیاده‌سازی نشده است.", None),
)
register(
"rag/chat-post_200_stream.json",
"POST",
"/api/rag/chat/",
200,
"RAG chat streaming response",
RAG_STREAM_SUCCESS,
)
register(
"rag/chat-post_400_missing_query.json",
"POST",
"/api/rag/chat/",
400,
"Missing query",
{"code": 400, "msg": "پارامتر query الزامی است."},
)
register(
"rag/chat-post_400_invalid_service.json",
"POST",
"/api/rag/chat/",
400,
"Invalid service id",
{"code": 400, "msg": "service_id نامعتبر است: unknown_service"},
)
register(
"rag/chat-post_400_missing_user.json",
"POST",
"/api/rag/chat/",
400,
"Missing user_id for service",
{"code": 400, "msg": "برای این service_id، پارامتر user_id الزامی است."},
)
register(
"rag/irrigation/post_202.json",
"POST",
"/api/rag/recommend/irrigation/",
202,
"RAG irrigation task queued",
queue_response(
"تسک توصیه آبیاری در صف قرار گرفت.",
"rag-irr-123",
"/api/rag/recommend/irrigation/rag-irr-123/status/",
),
)
register(
"rag/irrigation/post_400.json",
"POST",
"/api/rag/recommend/irrigation/",
400,
"RAG irrigation validation error",
error_response(400, "پارامتر sensor_uuid الزامی است.", None),
)
for name, payload in {
"pending": task_pending("rag-irr-123"),
"progress": task_progress("rag-irr-123", {"message": "در حال پردازش توصیه آبیاری..."}),
"success": task_success("rag-irr-123", IRRIGATION_RECOMMENDATION_RESULT),
"failure": task_failure("rag-irr-123", "خطا در دریافت توصیه آبیاری."),
}.items():
register(
f"rag/irrigation/status/get_200_{name}.json",
"GET",
"/api/rag/recommend/irrigation/{task_id}/status/",
200,
f"RAG irrigation status {name}",
payload,
)
register(
"rag/fertilization/post_202.json",
"POST",
"/api/rag/recommend/fertilization/",
202,
"RAG fertilization task queued",
queue_response(
"تسک توصیه کودهی در صف قرار گرفت.",
"rag-fert-123",
"/api/rag/recommend/fertilization/rag-fert-123/status/",
),
)
register(
"rag/fertilization/post_400.json",
"POST",
"/api/rag/recommend/fertilization/",
400,
"RAG fertilization validation error",
error_response(400, "پارامتر sensor_uuid الزامی است.", None),
)
for name, payload in {
"pending": task_pending("rag-fert-123"),
"progress": task_progress("rag-fert-123", {"message": "در حال پردازش توصیه کودهی..."}),
"success": task_success("rag-fert-123", FERTILIZATION_RECOMMENDATION_RESULT),
"failure": task_failure("rag-fert-123", "خطا در دریافت توصیه کودهی."),
}.items():
register(
f"rag/fertilization/status/get_200_{name}.json",
"GET",
"/api/rag/recommend/fertilization/{task_id}/status/",
200,
f"RAG fertilization status {name}",
payload,
)
register(
"farm-data/upsert-post_201.json",
"POST",
"/api/farm-data/",
201,
"Farm data created",
ok_response(SENSOR_DATA, code=201),
)
register(
"farm-data/upsert-post_400.json",
"POST",
"/api/farm-data/",
400,
"Farm data validation error",
error_response(400, "داده نامعتبر.", {"farm_uuid": ["This field is required."]}),
)
register(
"farm-data/upsert-post_404.json",
"POST",
"/api/farm-data/",
400,
"Farm data invalid boundary",
error_response(400, "داده نامعتبر.", {"farm_boundary": ["farm_boundary باید حداقل 3 گوشه معتبر داشته باشد."]}),
)
register(
"farm-data/parameters-post_201.json",
"POST",
"/api/farm-data/parameters/",
201,
"Create sensor parameter",
ok_response(SENSOR_PARAMETER, code=201),
)
register(
"farm-data/parameters-post_400.json",
"POST",
"/api/farm-data/parameters/",
400,
"Sensor parameter validation error",
error_response(400, "داده نامعتبر.", {"code": ["This field is required."]}),
)
(MOCK_DIR / "index.json").write_text(
json.dumps(index, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
if __name__ == "__main__":
main()