1qwsd commited on
Commit
6fd066f
ยท
verified ยท
1 Parent(s): f2dfe36

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +591 -765
src/streamlit_app.py CHANGED
@@ -3,9 +3,8 @@ import pandas as pd
3
  import numpy as np
4
  from datetime import datetime, timedelta
5
  import logging
6
- from pathlib import Path
7
  import requests
8
- from typing import Optional, Dict, List, Tuple, Any
9
  import json
10
  from io import BytesIO
11
  from PIL import Image
@@ -14,9 +13,12 @@ import os
14
  import sqlite3
15
  import hashlib
16
 
17
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
18
- # OPTIONAL DEPENDENCIES WITH FALLBACK
19
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
 
 
 
20
 
21
  # Image Recognition
22
  try:
@@ -62,404 +64,17 @@ except ImportError:
62
  logging.basicConfig(level=logging.INFO)
63
  logger = logging.getLogger(__name__)
64
 
65
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
66
- # LANGUAGE TRANSLATION DICTIONARY
67
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
68
-
69
- TRANSLATIONS = {
70
- "Hindi": {
71
- "title": "๐ŸŒพ เค•เคฟเคธเคพเคจ เคธเคพเคฅเฅ€ v4.0",
72
- "subtitle": "๐ŸŽค เค†เคตเคพเคœ เค•เฅ‡ เคฎเคพเคงเฅเคฏเคฎ เคธเฅ‡ เคฌเคพเคค เค•เคฐเฅ‡เค‚ - เค†เคธเคพเคจ เค”เคฐ เคธเคฐเคฒ!",
73
- "settings": "โš™๏ธ เคธเฅ‡เคŸเคฟเค‚เค—เฅเคธ",
74
- "location": "๐Ÿ“ เค†เคชเค•เคพ เคธเฅเคฅเคพเคจ",
75
- "language": "๐ŸŒ เคญเคพเคทเคพ",
76
- "alerts": "๐Ÿ”” เค…เคฒเคฐเฅเคŸ",
77
- "all_conditions_normal": "โœ… เคธเคญเฅ€ เคธเฅเคฅเคฟเคคเคฟเคฏเคพเค‚ เคธเคพเคฎเคพเคจเฅเคฏ เคนเฅˆเค‚!",
78
- "frost_risk": "โ„๏ธ เค เค‚เคก เค•เคพ เค–เคคเคฐเคพ! เคจเคพเคœเฅเค• เคซเคธเคฒเฅ‹เค‚ เค•เฅ‹ เคฌเคšเคพเคเค‚",
79
- "high_temp": "๐Ÿ”ฅ เค…เคงเคฟเค• เคคเคพเคชเคฎเคพเคจ! เคธเคฟเค‚เคšเคพเคˆ เคฌเคขเคผเคพเคเค‚",
80
- "high_humidity": "๐Ÿฆ  เค…เคงเคฟเค• เคจเคฎเฅ€! เค•เคตเค• เคฐเฅ‹เค—เฅ‹เค‚ เค•เฅ‡ เคฒเคฟเค เคธเคพเคตเคงเคพเคจ เคฐเคนเฅ‡เค‚",
81
- "voice_assistant": "๐Ÿ—ฃ๏ธ เค†เคตเคพเคœ เคธเคนเคพเคฏเค•",
82
- "weather": "๐ŸŒค๏ธ เคฎเฅŒเคธเคฎ",
83
- "market": "๐Ÿ’ฐ เคฌเคพเคœเคพเคฐ",
84
- "crops": "๐ŸŒฑ เคซเคธเคฒเฅ‡เค‚",
85
- "pests": "๐Ÿ› เค•เฅ€เคŸ",
86
- "irrigation": "๐Ÿ’ง เคธเคฟเค‚เคšเคพเคˆ",
87
- "analytics": "๐Ÿ“Š เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ",
88
- "disease": "๐Ÿ“ธ เคฐเฅ‹เค—",
89
- "other": "๐ŸŽค เค…เคจเฅเคฏ",
90
- "soil": "๐Ÿงช เคฎเคฟเคŸเฅเคŸเฅ€",
91
- "yield": "๐Ÿ“ˆ เคซเคธเคฒ",
92
- "profile": "๐Ÿ‘ค เคชเฅเคฐเฅ‹เคซเคพเค‡เคฒ",
93
- "speak_with_voice": "### ๐ŸŽค เค†เคตเคพเคœ เคธเฅ‡ เคฌเคพเคค เค•เคฐเฅ‡เค‚",
94
- "what_you_want": "#### เค•เฅเคฏเคพ เค†เคช เคœเคพเคจเคจเคพ เคšเคพเคนเคคเฅ‡ เคนเฅˆเค‚?",
95
- "rainfall_info": "เคฌเคพเคฐเคฟเคถ เค•เฅ€ เคœเคพเคจเค•เคพเคฐเฅ€",
96
- "pest_problem": "เค•เฅ€เคŸ เค•เฅ€ เคธเคฎเคธเฅเคฏเคพ",
97
- "market_prices": "เคฌเคพเคœเคพเคฐ เคญเคพเคต",
98
- "speak_question": "๐ŸŽ™๏ธ เค…เคชเคจเฅ€ เค†เคตเคพเคœ เคธเฅ‡ เคชเฅ‚เค›เฅ‡เค‚",
99
- "microphone_on": "๐ŸŽ™๏ธ เคฎเคพเค‡เค•เฅเคฐเฅ‹เคซเฅ‹เคจ เคšเคพเคฒเฅ‚ เค•เคฐเฅ‡เค‚",
100
- "hear_answer": "๐Ÿ”Š เคœเคตเคพเคฌ เคธเฅเคจเฅ‡เค‚",
101
- "listening": "๐ŸŽ™๏ธ เคธเฅเคจเคฟเค... เคฌเฅ‹เคฒเคฟเค!",
102
- "you_said": "เค†เคชเคจเฅ‡ เค•เคนเคพ:",
103
- "weather_unavailable": "เคฎเฅŒเคธเคฎ เคกเฅ‡เคŸเคพ เค‰เคชเคฒเคฌเฅเคง เคจเคนเฅ€เค‚ เคนเฅˆ",
104
- "upload_photo_disease": "๐Ÿ“ธ เคชเคคเฅเคคเฅ€ เค•เฅ€ เคซเฅ‹เคŸเฅ‹ เค…เคชเคฒเฅ‹เคก เค•เคฐเคจเฅ‡ เค•เฅ‡ เคฒเคฟเค 'เคฐเฅ‹เค—' เคŸเฅˆเคฌ เคชเคฐ เคœเคพเคเค‚",
105
- "go_disease_tab": "เค•เฅƒเคชเคฏเคพ เคฐเฅ‹เค— เคŸเฅˆเคฌ เคชเคฐ เคœเคพเค•เคฐ เคชเคคเฅเคคเฅ€ เค•เฅ€ เคคเคธเฅเคตเฅ€เคฐ เค…เคชเคฒเฅ‹เคก เค•เคฐเฅ‡เค‚",
106
- "browser_no_mic": "เค†เคชเค•เฅ‡ เคฌเฅเคฐเคพเค‰เคœเคผเคฐ เคฎเฅ‡เค‚ เคฎเคพเค‡เค•เฅเคฐเฅ‹เคซเฅ‹เคจ เคธเคชเฅ‹เคฐเฅเคŸ เคจเคนเฅ€เค‚ เคนเฅˆ",
107
- "weather_info": "### ๐ŸŒค๏ธ เคฎเฅŒเคธเคฎ เค•เฅ€ เคœเคพเคจเค•เคพเคฐเฅ€",
108
- "refresh_weather": "๐Ÿ”„ เคฎเฅŒเคธเคฎ เค…เคชเคกเฅ‡เคŸ เค•เคฐเฅ‡เค‚",
109
- "loading": "เคกเฅ‡เคŸเคพ เคฒเฅ‹เคก เคนเฅ‹ เคฐเคนเคพ เคนเฅˆ...",
110
- "temperature": "๐ŸŒก๏ธ เคคเคพเคชเคฎเคพเคจ",
111
- "humidity": "๐Ÿ’ง เคจเคฎเฅ€",
112
- "wind": "๐Ÿ’จ เคนเคตเคพ",
113
- "market_prices_title": "### ๐Ÿ’ฐ เคฌเคพเคœเคพเคฐ เคญเคพเคต",
114
- "refresh_prices": "๐Ÿ”„ เคญเคพเคต เค…เคชเคกเฅ‡เคŸ เค•เคฐเฅ‡เค‚",
115
- "per_quintal": "/เค•เฅเคตเคฟเค‚เคŸเคฒ",
116
- "crop_suggestions": "### ๐ŸŒฑ เคซเคธเคฒ เค•เฅ‡ เคธเฅเคเคพเคต",
117
- "best_crops": "๐Ÿ“ เค†เคชเค•เฅ‡ เค•เฅเคทเฅ‡เคคเฅเคฐ เคฎเฅ‡เค‚ เคธ๏ฟฝ๏ฟฝ๏ฟฝเฅเคตเคถเฅเคฐเฅ‡เคทเฅเค  เคซเคธเคฒเฅ‡เค‚: เค•เคชเคพเคธ, เค—เฅ‡เคนเฅ‚เค, เคšเคพเคตเคฒ, เค—เคจเฅเคจเคพ",
118
- "current_season": "๐Ÿ“… เคฎเฅŒเคธเคฎ:",
119
- "pest_management": "### ๐Ÿ› เค•เฅ€เคŸ เคชเฅเคฐเคฌเค‚เคงเคจ",
120
- "pest_info": "เค•เฅ€เคŸเฅ‹เค‚ เค•เฅ€ เคชเคนเคšเคพเคจ เค”เคฐ เคจเคฟเคฏเค‚เคคเฅเคฐเคฃ เค•เฅ‡ เคธเฅเคเคพเคต เคฏเคนเคพเค เคฎเคฟเคฒเฅ‡เค‚เค—เฅ‡",
121
- "irrigation_management": "### ๐Ÿ’ง เคธเคฟเค‚เคšเคพเคˆ เคชเฅเคฐเคฌเค‚เคงเคจ",
122
- "irrigation_info": "เคธเฅเคฎเคพเคฐเฅเคŸ เคธเคฟเค‚เคšเคพเคˆ เค…เคจเฅเคธเฅ‚เคšเฅ€ เค”เคฐ เคœเคฒ เคธเค‚เคฐเค•เฅเคทเคฃ เคŸเคฟเคชเฅเคธ",
123
- "farm_analytics": "### ๐Ÿ“Š เค–เฅ‡เคค เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ",
124
- "analytics_info": "เคฒเคพเคญ เค—เคฃเคจเคพ เค”เคฐ เค–เฅ‡เคค เค•เฅ‡ เค†เค‚เค•เคกเคผเฅ‡ เคฏเคนเคพเค เคฆเคฟเค–เฅ‡เค‚เค—เฅ‡",
125
- "disease_detection": "### ๐Ÿ“ธ เคฐเฅ‹เค— เคชเคนเคšเคพเคจ (เคชเคคเฅเคคเฅ€ เค•เฅ€ เคซเฅ‹เคŸเฅ‹ เคฒเค—เคพเคเค‚)",
126
- "upload_leaf": "๐Ÿ“ท เคชเคคเฅเคคเฅ€ เค•เฅ€ เคคเคธเฅเคตเฅ€เคฐ เคšเฅเคจเฅ‡เค‚",
127
- "your_photo": "เค†เคชเค•เฅ€ เคคเคธเฅเคตเฅ€เคฐ",
128
- "analyze": "๐Ÿ” เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ เค•เคฐเฅ‡เค‚",
129
- "analysis_complete": "โœ… เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ เคชเฅ‚เคฐเคพ!",
130
- "disease": "เคฐเฅ‹เค—",
131
- "confidence": "เคตเคฟเคถเฅเคตเคพเคธ",
132
- "severity": "เค—เค‚เคญเฅ€เคฐเคคเคพ",
133
- "image_recognition_unavailable": "โš ๏ธ เค›เคตเคฟ เคชเคนเคšเคพเคจ เค‰เคชเคฒเคฌเฅเคง เคจเคนเฅ€เค‚ เคนเฅˆ",
134
- "soil_check": "### ๐Ÿงช เคฎเคฟเคŸเฅเคŸเฅ€ เค•เฅ€ เคœเคพเค‚เคš",
135
- "soil_ph": "เคฎเคฟเคŸเฅเคŸเฅ€ เค•เคพ pH",
136
- "nitrogen": "เคจเคพเค‡เคŸเฅเคฐเฅ‹เคœเคจ (mg/kg)",
137
- "phosphorus": "เคซเฅ‰เคธเฅเคซเฅ‹เคฐเคธ (mg/kg)",
138
- "potassium": "เคชเฅ‹เคŸเฅ‡เคถเคฟเคฏเคฎ (mg/kg)",
139
- "organic_matter": "เคœเฅˆเคต เคชเคฆเคพเคฐเฅเคฅ (%)",
140
- "moisture": "เคจเคฎเฅ€ (%)",
141
- "save_soil_test": "๐Ÿ’พ เคฎเคฟเคŸเฅเคŸเฅ€ เคชเคฐเฅ€เค•เฅเคทเคฃ เคธเคนเฅ‡เคœเฅ‡เค‚",
142
- "saved": "โœ… เคธเคนเฅ‡เคœเคพ เค—เคฏเคพ!",
143
- "recommendations": "### ๐Ÿ“‹ เคธเฅเคเคพเคต:",
144
- "acidic_soil": "๐Ÿ”ด **เค…เคฎเฅเคฒเฅ€เคฏ เคฎเคฟเคŸเฅเคŸเฅ€**: เคšเฅ‚เคจเคพ (CaCO3) เคฒเค—เคพเคเค‚",
145
- "alkaline_soil": "๐Ÿ”ด **เค•เฅเคทเคพเคฐเฅ€เคฏ เคฎเคฟเคŸเฅเคŸเฅ€**: เค—เค‚เคงเค• เคฏเคพ เคœเฅˆเคต เคชเคฆเคพเคฐเฅเคฅ เคฒเค—เคพเคเค‚",
146
- "ideal_ph": "โœ… **เค†เคฆเคฐเฅเคถ pH**: 6.5-7.5 เค•เฅ‡ เคฌเฅ€เคš เค…เคšเฅเค›เคพ เคนเฅˆ",
147
- "low_nitrogen": "๐ŸŸก **เค•เคฎ เคจเคพเค‡เคŸเฅเคฐเฅ‹เคœเคจ**: NPK 20:20:0 เคฒเค—เคพเคเค‚",
148
- "high_nitrogen": "๐ŸŸก **เค…เคงเคฟเค• เคจเคพเค‡เคŸเฅเคฐเฅ‹เคœเคจ**: เคจเคพเค‡เคŸเฅเคฐเฅ‹เคœเคจ เค•เคฎ เค•เคฐเฅ‡เค‚",
149
- "ideal_nitrogen": "โœ… **เค†เคฆเคฐเฅเคถ เคจเคพเค‡เคŸเฅเคฐเฅ‹เคœเคจ**: เค…เคšเฅเค›เคพ เคธเฅเคคเคฐ",
150
- "low_phosphorus": "๐ŸŸก **เค•เคฎ เคซเฅ‰เคธเฅเคซเฅ‹เคฐเคธ**: DAP เคฏเคพ SSP เคฒเค—เคพเคเค‚",
151
- "ideal_phosphorus": "โœ… **เค†เคฆเคฐเฅเคถ เคซเฅ‰เคธเฅเคซเฅ‹เคฐเคธ**: เค…เคšเฅเค›เคพ เคธเฅเคคเคฐ",
152
- "low_potassium": "๐ŸŸก **เค•เคฎ เคชเฅ‹เคŸเฅ‡เคถเคฟเคฏเคฎ**: KCl เคฏเคพ MOP เคฒเค—เคพเคเค‚",
153
- "ideal_potassium": "โœ… **เค†เคฆเคฐเฅเคถ เคชเฅ‹เคŸเฅ‡เคถเคฟเคฏเคฎ**: เค…เคšเฅเค›เคพ เคธเฅเคคเคฐ",
154
- "yield_prediction": "### ๐Ÿ“ˆ เคซเคธเคฒ เค•เฅ€ เค‰เคชเคœ เค•เคพ เค…เคจเฅเคฎเคพเคจ",
155
- "temp_celsius": "เคคเคพเคชเคฎเคพเคจ (ยฐC)",
156
- "humidity_percent": "เคจเคฎเฅ€ (%)",
157
- "rainfall_mm": "เคฌเคพเคฐเคฟเคถ (mm)",
158
- "predict_yield": "๐Ÿ”ฎ เค‰เคชเคœ เค•เฅ€ เคญเคตเคฟเคทเฅเคฏเคตเคพเคฃเฅ€ เค•เคฐเฅ‡เค‚",
159
- "estimated_yield": "๐Ÿ“ˆ เค…เคจเฅเคฎเคพเคจเคฟเคค เค‰เคชเคœ:",
160
- "quintal_hectare": "เค•เฅเคตเคฟเค‚เคŸเคฒ/เคนเฅ‡เค•เฅเคŸเฅ‡เคฏเคฐ",
161
- "high_yield": "โœ… เค‰เคšเฅเคš เค‰เคชเคœ เค•เฅ€ เค‰เคฎเฅเคฎเฅ€เคฆ เคนเฅˆ!",
162
- "average_yield": "๐Ÿ“Š เค”เคธเคค เค‰เคชเคœ เค•เฅ€ เค‰เคฎเฅเคฎเฅ€เคฆ เคนเฅˆ",
163
- "low_yield": "โš ๏ธ เค•เคฎ เค‰เคชเคœ เคนเฅ‹ เคธเค•เคคเฅ€ เคนเฅˆเฅค เคฎเคฟเคŸเฅเคŸเฅ€ เค”เคฐ เคฎเฅŒเคธเคฎ เค•เฅ€ เคœเคพเค‚เคš เค•เคฐเฅ‡เค‚",
164
- "profile_settings": "### ๐Ÿ‘ค เคชเฅเคฐเฅ‹เคซเคพเค‡เคฒ & เคธเฅ‡เคŸเคฟเค‚เค—เฅเคธ",
165
- "choose_option": "เคตเคฟเค•เคฒเฅเคช เคšเฅเคจเฅ‡เค‚",
166
- "login": "๐Ÿ” เคฒเฅ‰เค—เคฟเคจ",
167
- "register": "๐Ÿ“ เคฐเคœเคฟเคธเฅเคŸเคฐ",
168
- "login_title": "เคฒเฅ‰เค—เคฟเคจ เค•เคฐเฅ‡เค‚",
169
- "username": "เค‰เคชเคฏเฅ‹เค—เค•เคฐเฅเคคเคพ เคจเคพเคฎ",
170
- "password": "เคชเคพเคธเคตเคฐเฅเคก",
171
- "login_btn": "เคฒเฅ‰เค—เคฟเคจ",
172
- "login_success": "โœ… เคฒเฅ‰เค—เคฟเคจ เคธเคซเคฒ!",
173
- "invalid_credentials": "โŒ เค—เคฒเคค เค•เฅเคฐเฅ‡เคกเฅ‡เค‚เคถเคฟเคฏเคฒเฅเคธ",
174
- "register_title": "เคจเคฏเคพ เค–เคพเคคเคพ เคฌเคจเคพเคเค‚",
175
- "email": "เคˆเคฎเฅ‡เคฒ",
176
- "register_btn": "เคฐเคœเคฟเคธเฅเคŸเคฐ",
177
- "registration_success": "โœ… เคฐเคœเคฟเคธเฅเคŸเฅเคฐเฅ‡เคถเคจ เคธเคซเคฒ! เค…เคฌ เคฒเฅ‰เค—เคฟเคจ เค•เคฐเฅ‡เค‚",
178
- "logged_in_as": "โœ… เคฒเฅ‰เค—เคฟเคจ เค•เคฟเคฏเคพ เคนเฅเค†:",
179
- "logout_btn": "เคฒเฅ‰เค—เค†เค‰เคŸ",
180
- "footer": "๐ŸŒพ เค•เคฟเคธเคพเคจ เคธเคพเคฅเฅ€ v4.0 - เคธเคญเฅ€ เค•เคฟเคธเคพเคจเฅ‹เค‚ เค•เฅ‡ เคฒเคฟเค | ๐Ÿšœ เค†เคธเคพเคจ, เคธเคฐเคฒ, เค”เคฐ เคฎเฅเคซเฅเคค",
181
- "kharif": "เค–เคฐเฅ€เคซ (Kharif)",
182
- "rabi": "เคฐเคฌเฅ€ (Rabi)",
183
- "summer": "เค—เคฐเฅเคฎเฅ€ (Summer)",
184
- "wheat": "เค—เฅ‡เคนเฅ‚เค (Wheat)",
185
- "rice": "เคšเคพเคตเคฒ (Rice)",
186
- "cotton": "เค•เคชเคพเคธ (Cotton)",
187
- "sugarcane": "เค—เคจเฅเคจเคพ (Sugarcane)",
188
- "potato": "เค†เคฒเฅ‚ (Potato)",
189
- "tomato": "เคŸเคฎเคพเคŸเคฐ (Tomato)",
190
- "onion": "เคชเฅเคฏเคพเคœ (Onion)",
191
- "corn": "เคฎเค•เฅเค•เคพ (Corn)",
192
- },
193
-
194
- "English": {
195
- "title": "๐ŸŒพ Farmer Copilot v4.0",
196
- "subtitle": "๐ŸŽค Speak with Voice - Easy and Simple!",
197
- "settings": "โš™๏ธ Settings",
198
- "location": "๐Ÿ“ Your Location",
199
- "language": "๐ŸŒ Language",
200
- "alerts": "๐Ÿ”” Alerts",
201
- "all_conditions_normal": "โœ… All conditions normal!",
202
- "frost_risk": "โ„๏ธ Frost Risk! Protect delicate crops",
203
- "high_temp": "๐Ÿ”ฅ High Temperature! Increase irrigation",
204
- "high_humidity": "๐Ÿฆ  High Humidity! Watch for fungal diseases",
205
- "voice_assistant": "๐Ÿ—ฃ๏ธ Voice Assistant",
206
- "weather": "๐ŸŒค๏ธ Weather",
207
- "market": "๐Ÿ’ฐ Market",
208
- "crops": "๐ŸŒฑ Crops",
209
- "pests": "๐Ÿ› Pests",
210
- "irrigation": "๐Ÿ’ง Irrigation",
211
- "analytics": "๐Ÿ“Š Analytics",
212
- "disease": "๐Ÿ“ธ Disease",
213
- "other": "๐ŸŽค Other",
214
- "soil": "๐Ÿงช Soil",
215
- "yield": "๐Ÿ“ˆ Yield",
216
- "profile": "๐Ÿ‘ค Profile",
217
- "speak_with_voice": "### ๐ŸŽค Speak with Your Voice",
218
- "what_you_want": "#### What do you want to know?",
219
- "rainfall_info": "Rainfall Information",
220
- "pest_problem": "Pest Problem",
221
- "market_prices": "Market Prices",
222
- "speak_question": "๐ŸŽ™๏ธ Ask with Your Voice",
223
- "microphone_on": "๐ŸŽ™๏ธ Turn On Microphone",
224
- "hear_answer": "๐Ÿ”Š Hear Answer",
225
- "listening": "๐ŸŽ™๏ธ Listening... Speak now!",
226
- "you_said": "You said:",
227
- "weather_unavailable": "Weather data not available",
228
- "upload_photo_disease": "๐Ÿ“ธ Upload leaf photo in Disease tab",
229
- "go_disease_tab": "Please go to Disease tab and upload leaf photo",
230
- "browser_no_mic": "Your browser does not support microphone",
231
- "weather_info": "### ๐ŸŒค๏ธ Weather Information",
232
- "refresh_weather": "๐Ÿ”„ Refresh Weather",
233
- "loading": "Loading data...",
234
- "temperature": "๐ŸŒก๏ธ Temperature",
235
- "humidity": "๐Ÿ’ง Humidity",
236
- "wind": "๐Ÿ’จ Wind",
237
- "market_prices_title": "### ๐Ÿ’ฐ Market Prices",
238
- "refresh_prices": "๐Ÿ”„ Refresh Prices",
239
- "per_quintal": "/quintal",
240
- "crop_suggestions": "### ๐ŸŒฑ Crop Suggestions",
241
- "best_crops": "๐Ÿ“ Best crops for your region: Cotton, Wheat, Rice, Sugarcane",
242
- "current_season": "๐Ÿ“… Season:",
243
- "pest_management": "### ๐Ÿ› Pest Management",
244
- "pest_info": "Pest identification and control tips here",
245
- "irrigation_management": "### ๐Ÿ’ง Irrigation Management",
246
- "irrigation_info": "Smart irrigation schedule and water conservation tips",
247
- "farm_analytics": "### ๐Ÿ“Š Farm Analytics",
248
- "analytics_info": "Profit calculation and farm statistics here",
249
- "disease_detection": "### ๐Ÿ“ธ Disease Detection (Upload Leaf Photo)",
250
- "upload_leaf": "๐Ÿ“ท Choose Leaf Photo",
251
- "your_photo": "Your Photo",
252
- "analyze": "๐Ÿ” Analyze",
253
- "analysis_complete": "โœ… Analysis Complete!",
254
- "disease": "Disease",
255
- "confidence": "Confidence",
256
- "severity": "Severity",
257
- "image_recognition_unavailable": "โš ๏ธ Image recognition not available",
258
- "soil_check": "### ๐Ÿงช Soil Check",
259
- "soil_ph": "Soil pH",
260
- "nitrogen": "Nitrogen (mg/kg)",
261
- "phosphorus": "Phosphorus (mg/kg)",
262
- "potassium": "Potassium (mg/kg)",
263
- "organic_matter": "Organic Matter (%)",
264
- "moisture": "Moisture (%)",
265
- "save_soil_test": "๐Ÿ’พ Save Soil Test",
266
- "saved": "โœ… Saved!",
267
- "recommendations": "### ๐Ÿ“‹ Recommendations:",
268
- "acidic_soil": "๐Ÿ”ด **Acidic Soil**: Apply lime (CaCO3)",
269
- "alkaline_soil": "๐Ÿ”ด **Alkaline Soil**: Apply sulfur or organic matter",
270
- "ideal_ph": "โœ… **Ideal pH**: Between 6.5-7.5",
271
- "low_nitrogen": "๐ŸŸก **Low Nitrogen**: Apply NPK 20:20:0",
272
- "high_nitrogen": "๐ŸŸก **High Nitrogen**: Reduce nitrogen fertilizer",
273
- "ideal_nitrogen": "โœ… **Ideal Nitrogen**: Good level",
274
- "low_phosphorus": "๐ŸŸก **Low Phosphorus**: Apply DAP or SSP",
275
- "ideal_phosphorus": "โœ… **Ideal Phosphorus**: Good level",
276
- "low_potassium": "๐ŸŸก **Low Potassium**: Apply KCl or MOP",
277
- "ideal_potassium": "โœ… **Ideal Potassium**: Good level",
278
- "yield_prediction": "### ๐Ÿ“ˆ Crop Yield Prediction",
279
- "temp_celsius": "Temperature (ยฐC)",
280
- "humidity_percent": "Humidity (%)",
281
- "rainfall_mm": "Rainfall (mm)",
282
- "predict_yield": "๐Ÿ”ฎ Predict Yield",
283
- "estimated_yield": "๐Ÿ“ˆ Estimated Yield:",
284
- "quintal_hectare": "quintal/hectare",
285
- "high_yield": "โœ… High yield expected!",
286
- "average_yield": "๐Ÿ“Š Average yield expected",
287
- "low_yield": "โš ๏ธ Low yield possible. Check soil and weather",
288
- "profile_settings": "### ๐Ÿ‘ค Profile & Settings",
289
- "choose_option": "Choose Option",
290
- "login": "๐Ÿ” Login",
291
- "register": "๐Ÿ“ Register",
292
- "login_title": "Login",
293
- "username": "Username",
294
- "password": "Password",
295
- "login_btn": "Login",
296
- "login_success": "โœ… Login successful!",
297
- "invalid_credentials": "โŒ Invalid credentials",
298
- "register_title": "Create New Account",
299
- "email": "Email",
300
- "register_btn": "Register",
301
- "registration_success": "โœ… Registration successful! Login now",
302
- "logged_in_as": "โœ… Logged in as:",
303
- "logout_btn": "Logout",
304
- "footer": "๐ŸŒพ Farmer Copilot v4.0 - For All Farmers | ๐Ÿšœ Easy, Simple, and Free",
305
- "kharif": "Kharif",
306
- "rabi": "Rabi",
307
- "summer": "Summer",
308
- "wheat": "Wheat",
309
- "rice": "Rice",
310
- "cotton": "Cotton",
311
- "sugarcane": "Sugarcane",
312
- "potato": "Potato",
313
- "tomato": "Tomato",
314
- "onion": "Onion",
315
- "corn": "Corn",
316
- },
317
-
318
- "Marathi": {
319
- "title": "๐ŸŒพ เคถเฅ‡เคคเค•เคฐเฅ€ เคธเคนเค•เคพเคฐ v4.0",
320
- "subtitle": "๐ŸŽค เค†เคตเคพเคœเคพเคจเฅ‡ เคฌเฅ‹เคฒเคพ - เคธเฅ‹เคชเฅ‡ เค†เคฃเคฟ เคธเคฐเคฒ!",
321
- "settings": "โš™๏ธ เคธเฅ‡เคŸเคฟเค‚เค—เฅเคธ",
322
- "location": "๐Ÿ“ เค†เคชเคฒเฅ‡ เคธเฅเคฅเคพเคจ",
323
- "language": "๐ŸŒ เคญเคพเคทเคพ",
324
- "alerts": "๐Ÿ”” เคธเฅ‚เคšเคจเคพ",
325
- "all_conditions_normal": "โœ… เคธเคฐเฅเคต เคธเฅเคฅเคฟเคคเฅ€ เคธเคพเคฎเคพเคจเฅเคฏ เค†เคนเฅ‡!",
326
- "frost_risk": "โ„๏ธ เคนเคฟเคฎเคพเค‚เค•เคพเคšเคพ เคงเฅ‹เค•เคพ! เคจเคพเคœเฅ‚เค• เคชเคฟเค•เคพเค‚เคšเฅ‡ เคธเค‚เคฐเค•เฅเคทเคฃ เค•เคฐเคพ",
327
- "high_temp": "๐Ÿ”ฅ เค‰เคšเฅเคš เคคเคพเคชเคฎเคพเคจ! เคธเคฟเค‚เคšเคพเคˆ เคตเคพเคขเคตเคพ",
328
- "high_humidity": "๐Ÿฆ  เค‰เคšเฅเคš เค†เคฐเฅเคฆเฅเคฐเคคเคพ! เคฌเฅเคฐเคถเฅ€ เคฐเฅ‹เค—เคพเค‚เคธเคพเค เฅ€ เคธเคพเคตเคงเคพเคจ เคฐเคนเคพ",
329
- "voice_assistant": "๐Ÿ—ฃ๏ธ เค†เคตเคพเคœ เคธเคนเคพเคฏเค•",
330
- "weather": "๐ŸŒค๏ธ เคนเคตเคพเคฎเคพเคจ",
331
- "market": "๐Ÿ’ฐ เคฌเคพเคœเคพเคฐ",
332
- "crops": "๐ŸŒฑ เคชเคฟเค•เฅ‡",
333
- "pests": "๐Ÿ› เค•เฅ€เคŸเค•",
334
- "irrigation": "๐Ÿ’ง เคธเคฟเค‚เคšเคจ",
335
- "analytics": "๐Ÿ“Š เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ",
336
- "disease": "๐Ÿ“ธ เคฐเฅ‹เค—",
337
- "other": "๐ŸŽค เค‡เคคเคฐ",
338
- "soil": "๐Ÿงช เคฎเคพเคคเฅ€เคšเคพ",
339
- "yield": "๐Ÿ“ˆ เค‰เคคเฅเคชเคพเคฆเคจ",
340
- "profile": "๐Ÿ‘ค เคชเฅเคฐเฅ‹เคซเคพเค‡เคฒ",
341
- "speak_with_voice": "### ๐ŸŽค เค†เคตเคพเคœเคพเคจเฅ‡ เคฌเฅ‹เคฒเคพ",
342
- "what_you_want": "#### เคคเฅเคฎเฅเคนเคพเคฒเคพ เค•เคพเคฏ เคœเคพเคฃเฅ‚เคจ เค˜เฅเคฏเคพเคฏเคšเฅ‡ เค†เคนเฅ‡?",
343
- "rainfall_info": "เคชเคพเคŠเคธ เคฎเคพเคนเคฟเคคเฅ€",
344
- "pest_problem": "เค•เฅ€เคŸเค• เคธเคฎเคธเฅเคฏเคพ",
345
- "market_prices": "เคฌเคพเคœเคพเคฐ เคฆเคฐ",
346
- "speak_question": "๐ŸŽ™๏ธ เค†เคตเคพเคœเคพเคจเฅ‡ เคชเฅเคฐเคถเฅเคจ เคตเคฟเคšเคพเคฐเคพ",
347
- "microphone_on": "๐ŸŽ™๏ธ เคฎเคพเคฏเค•เฅเคฐเฅ‹เคซเฅ‹เคจ เคšเคพเคฒเฅ‚ เค•เคฐเคพ",
348
- "hear_answer": "๐Ÿ”Š เค‰เคคเฅเคคเคฐ เคเค•เคพ",
349
- "listening": "๐ŸŽ™๏ธ เคเค•เคคเฅ‹ เค†เคนเฅ‡... เคฌเฅ‹เคฒเคพ!",
350
- "you_said": "เคคเฅเคฎเฅเคนเฅ€ เคฎเฅเคนเคฃเคพเคฒเคพเคค:",
351
- "weather_unavailable": "เคนเคตเคพเคฎเคพเคจ เคกเฅ‡เคŸเคพ เค‰เคชเคฒเคฌเฅเคง เคจเคพเคนเฅ€",
352
- "upload_photo_disease": "๐Ÿ“ธ เคฐเฅ‹เค— เคŸเฅ…เคฌเคฎเคงเฅเคฏเฅ‡ เคชเคพเคจ เคซเฅ‹เคŸเฅ‹ เค…เคชเคฒเฅ‹เคก เค•เคฐเคพ",
353
- "go_disease_tab": "เค•เฅƒเคชเคฏเคพ เคฐเฅ‹เค— เคŸเฅ…เคฌเคฎเคงเฅเคฏเฅ‡ เคœเคพ เค†เคฃเคฟ เคชเคพเคจ เคซเฅ‹เคŸเฅ‹ เค…เคชเคฒเฅ‹เคก เค•เคฐเคพ",
354
- "browser_no_mic": "เค†เคชเคฒเฅเคฏเคพ เคฌเฅเคฐเคพเค‰เคœเคฐเคฒเคพ เคฎเคพเคฏเค•เฅเคฐเฅ‹เคซเฅ‹เคจ เคธเคฎเคฐเฅเคฅเคจ เคจเคพเคนเฅ€",
355
- "weather_info": "### ๐ŸŒค๏ธ เคนเคตเคพเคฎเคพเคจ เคฎเคพเคนเคฟเคคเฅ€",
356
- "refresh_weather": "๐Ÿ”„ เคนเคตเคพเคฎเคพเคจ เคคเคพเคœเฅ‡ เค•เคฐเคพ",
357
- "loading": "เคกเฅ‡เคŸเคพ เคฒเฅ‹เคก เคนเฅ‹เคค เค†เคนเฅ‡...",
358
- "temperature": "๐ŸŒก๏ธ เคคเคพเคชเคฎเคพเคจ",
359
- "humidity": "๐Ÿ’ง เค†เคฐเฅเคฆเฅเคฐเคคเคพ",
360
- "wind": "๐Ÿ’จ เคตเคพเคฐเคพ",
361
- "market_prices_title": "### ๐Ÿ’ฐ เคฌเคพเคœเคพเคฐ เคฆเคฐ",
362
- "refresh_prices": "๐Ÿ”„ เคฆเคฐ เคคเคพเคœเฅ‡ เค•เคฐเคพ",
363
- "per_quintal": "/เค•เฅเคตเคฟเค‚เคŸเคฒ",
364
- "crop_suggestions": "### ๐ŸŒฑ เคชเคฟเค•เคพเค‚เคšเฅ‡ เคธเฅ‚เคšเคจ",
365
- "best_crops": "๐Ÿ“ เค†เคชเคฒเฅเคฏเคพ เคชเฅเคฐเคฆเฅ‡เคถเคพเคธเคพเค เฅ€ เค‰เคคเฅเคคเคฎ เคชเคฟเค•เฅ‡: เค•เคชเคพเคธ, เค—เคนเฅ‚, เคคเคพเค‚เคฆเฅ‚เคณ, เคŠเคธ",
366
- "current_season": "๐Ÿ“… เค‹เคคเฅ:",
367
- "pest_management": "### ๐Ÿ› เค•เฅ€เคŸเค• เคตเฅเคฏเคตเคธเฅเคฅเคพเคชเคจ",
368
- "pest_info": "เค•เฅ€เคŸเค• เค“เคณเค– ๏ฟฝ๏ฟฝเคฃเคฟ เคจเคฟเคฏเค‚เคคเฅเคฐเคฃ เคธเฅ‚เคšเคจเคพ เคฏเฅ‡เคฅเฅ‡",
369
- "irrigation_management": "### ๐Ÿ’ง เคธเคฟเค‚เคšเคจ เคตเฅเคฏเคตเคธเฅเคฅเคพเคชเคจ",
370
- "irrigation_info": "เคธเฅเคฎเคพเคฐเฅเคŸ เคธเคฟเค‚เคšเคจ เคตเฅ‡เคณเคพเคชเคคเฅเคฐเค• เค†เคฃเคฟ เคœเคฒ เคธเค‚เคฐเค•เฅเคทเคฃ เคธเฅ‚เคšเคจเคพ",
371
- "farm_analytics": "### ๐Ÿ“Š เคถเฅ‡เคค เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ",
372
- "analytics_info": "เคฒเคพเคญ เค—เคฃเคจเคพ เค†เคฃเคฟ เคถเฅ‡เคค เคธเคพเค‚เค–เฅเคฏเคฟเค•เฅ€ เคฏเฅ‡เคฅเฅ‡",
373
- "disease_detection": "### ๐Ÿ“ธ เคฐเฅ‹เค— เคถเฅ‹เคง (เคชเคพเคจ เคซเฅ‹เคŸเฅ‹ เค…เคชเคฒเฅ‹เคก เค•เคฐเคพ)",
374
- "upload_leaf": "๐Ÿ“ท เคชเคพเคจ เคซเฅ‹เคŸเฅ‹ เคจเคฟเคตเคกเคพ",
375
- "your_photo": "เค†เคชเคฒเคพ เคซเฅ‹เคŸเฅ‹",
376
- "analyze": "๐Ÿ” เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ เค•เคฐเคพ",
377
- "analysis_complete": "โœ… เคตเคฟเคถเฅเคฒเฅ‡เคทเคฃ เคชเฅ‚เคฐเฅเคฃ!",
378
- "disease": "เคฐเฅ‹เค—",
379
- "confidence": "เค†เคคเฅเคฎเคตเคฟเคถเฅเคตเคพเคธ",
380
- "severity": "เคคเฅ€เคตเฅเคฐเคคเคพ",
381
- "image_recognition_unavailable": "โš ๏ธ เคชเฅเคฐเคคเคฟเคฎเคพ เค“เคณเค– เค‰เคชเคฒเคฌเฅเคง เคจเคพเคนเฅ€",
382
- "soil_check": "### ๐Ÿงช เคฎเคพเคคเฅ€ เคคเคชเคพเคธเคพ",
383
- "soil_ph": "เคฎเคพเคคเฅ€เคšเคพ pH",
384
- "nitrogen": "เคจเคพเคฏเคŸเฅเคฐเฅ‹เคœเคจ (เคฎเคฟเค—เฅเคฐเคพ/เค•เคฟเค—เฅเคฐเคพ)",
385
- "phosphorus": "เคซเฅ‰เคธเฅเคซเคฐเคธ (เคฎเคฟเค—เฅเคฐเคพ/เค•เคฟเค—เฅเคฐเคพ)",
386
- "potassium": "เคชเฅ‹เคŸเฅ…เคถเคฟเคฏเคฎ (เคฎเคฟเค—เฅเคฐเคพ/เค•เคฟเค—เฅเคฐเคพ)",
387
- "organic_matter": "เคธเฅ‡เค‚เคฆเฅเคฐเคฟเคฏ เคชเคฆเคพเคฐเฅเคฅ (%)",
388
- "moisture": "เค“เคฒเคพเคตเคพ (%)",
389
- "save_soil_test": "๐Ÿ’พ เคฎเคพเคคเฅ€ เคšเคพเคšเคฃเฅ€ เคธเฅ‡เคตเฅเคน เค•เคฐเคพ",
390
- "saved": "โœ… เคธเฅ‡เคตเฅเคน เค•เฅ‡เคฒเฅ‡!",
391
- "recommendations": "### ๐Ÿ“‹ เคธเฅ‚เคšเคจเคพ:",
392
- "acidic_soil": "๐Ÿ”ด **เค…เคฎเฅเคฒเฅ€เคฏ เคฎเคพเคคเฅ€**: เคšเฅ‚เคจเคพ (CaCO3) เคฒเคพเคตเคพ",
393
- "alkaline_soil": "๐Ÿ”ด **เค•เฅเคทเคพเคฐเฅ€เคฏ เคฎเคพเคคเฅ€**: เค—เค‚เคงเค• เค•เคฟเค‚เคตเคพ เคธเฅ‡เค‚เคฆเฅเคฐเคฟเคฏ เคชเคฆเคพเคฐเฅเคฅ เคฒเคพเคตเคพ",
394
- "ideal_ph": "โœ… **เค†เคฆเคฐเฅเคถ pH**: 6.5-7.5 เคฆเคฐเคฎเฅเคฏเคพเคจ",
395
- "low_nitrogen": "๐ŸŸก **เค•เคฎเฅ€ เคจเคพเคฏเคŸเฅเคฐเฅ‹เคœเคจ**: NPK 20:20:0 เคฒเคพเคตเคพ",
396
- "high_nitrogen": "๐ŸŸก **เค‰เคšเฅเคš เคจเคพเคฏเคŸเฅเคฐเฅ‹เคœเคจ**: เคจเคพเคฏเคŸเฅเคฐเฅ‹เคœเคจ เค•เคฎเฅ€ เค•เคฐเคพ",
397
- "ideal_nitrogen": "โœ… **เค†เคฆเคฐเฅเคถ เคจเคพเคฏเคŸเฅเคฐเฅ‹เคœเคจ**: เคšเคพเค‚เค—เคฒเคพ เคธเฅเคคเคฐ",
398
- "low_phosphorus": "๐ŸŸก **เค•เคฎเฅ€ เคซเฅ‰เคธเฅเคซเคฐเคธ**: DAP เค•เคฟเค‚เคตเคพ SSP เคฒเคพเคตเคพ",
399
- "ideal_phosphorus": "โœ… **เค†เคฆเคฐเฅเคถ เคซเฅ‰เคธเฅเคซเคฐเคธ**: เคšเคพเค‚เค—เคฒเคพ เคธเฅเคคเคฐ",
400
- "low_potassium": "๐ŸŸก **เค•เคฎเฅ€ เคชเฅ‹เคŸเฅ…เคถเคฟเคฏเคฎ**: KCl เค•เคฟเค‚เคตเคพ MOP เคฒเคพเคตเคพ",
401
- "ideal_potassium": "โœ… **เค†เคฆเคฐเฅเคถ เคชเฅ‹เคŸเฅ…เคถเคฟเคฏเคฎ**: เคšเคพเค‚เค—เคฒเคพ เคธเฅเคคเคฐ",
402
- "yield_prediction": "### ๐Ÿ“ˆ เคชเคฟเค• เค‰เคคเฅเคชเคพเคฆเคจ เค…เค‚เคฆเคพเคœ",
403
- "temp_celsius": "เคคเคพเคชเคฎเคพเคจ (ยฐC)",
404
- "humidity_percent": "เค†เคฐเฅเคฆเฅเคฐเคคเคพ (%)",
405
- "rainfall_mm": "เคชเคพเคŠเคธ (เคฎเคฟเคฎเฅ€)",
406
- "predict_yield": "๐Ÿ”ฎ เค‰เคคเฅเคชเคพเคฆเคจ เค…เค‚เคฆเคพเคœ เคฒเคพเคตเคพ",
407
- "estimated_yield": "๐Ÿ“ˆ เค…เค‚เคฆเคพเคœเฅ‡ เค‰เคคเฅเคชเคพเคฆเคจ:",
408
- "quintal_hectare": "เค•เฅเคตเคฟเค‚เคŸเคฒ/เคนเฅ‡เค•เฅเคŸเคฐ",
409
- "high_yield": "โœ… เค‰เคšเฅเคš เค‰เคคเฅเคชเคพเคฆเคจ เค…เคชเฅ‡เค•เฅเคทเคฟเคค เค†เคนเฅ‡!",
410
- "average_yield": "๐Ÿ“Š เคธเคฐเคพเคธเคฐเฅ€ เค‰เคคเฅเคชเคพเคฆเคจ เค…เคชเฅ‡เค•เฅเคทเคฟเคค เค†เคนเฅ‡",
411
- "low_yield": "โš ๏ธ เค•เคฎเฅ€ เค‰เคคเฅเคชเคพเคฆเคจ เคธเค‚เคญเคต เค†เคนเฅ‡เฅค เคฎเคพเคคเฅ€ เค†เคฃเคฟ เคนเคตเคพเคฎเคพเคจ เคคเคชเคพเคธเคพ",
412
- "profile_settings": "### ๐Ÿ‘ค เคชเฅเคฐเฅ‹เคซเคพเค‡เคฒ เค†เคฃเคฟ เคธเฅ‡เคŸเคฟเค‚เค—เฅเคธ",
413
- "choose_option": "เคชเคฐเฅเคฏเคพเคฏ เคจเคฟเคตเคกเคพ",
414
- "login": "๐Ÿ” เคฒเฅ‰เค—เคฟเคจ",
415
- "register": "๐Ÿ“ เคจเฅ‹เค‚เคฆเคฃเฅ€",
416
- "login_title": "เคฒเฅ‰เค—เคฟเคจ เค•เคฐเคพ",
417
- "username": "เคตเคพเคชเคฐเค•เคฐเฅเคคเคพ เคจเคพเคต",
418
- "password": "เคชเคพเคธเคตเคฐเฅเคก",
419
- "login_btn": "เคฒเฅ‰เค—เคฟเคจ",
420
- "login_success": "โœ… เคฒเฅ‰เค—เคฟเคจ เคฏเคถเคธเฅเคตเฅ€!",
421
- "invalid_credentials": "โŒ เค…เคฏเฅ‹เค—เฅเคฏ เค•เฅเคฐเฅ‡เคกเฅ‡เค‚เคถเคฟเคฏเคฒเฅเคธ",
422
- "register_title": "เคจเคตเฅ€เคจ เค–เคพเคคเฅ‡ เคคเคฏเคพเคฐ เค•เคฐเคพ",
423
- "email": "เคˆเคฎเฅ‡เคฒ",
424
- "register_btn": "เคจเฅ‹เค‚เคฆเคฃเฅ€",
425
- "registration_success": "โœ… เคจเฅ‹เค‚เคฆเคฃเฅ€ เคฏเคถเคธเฅเคตเฅ€! เค†เคคเคพ เคฒเฅ‰เค—เคฟเคจ เค•เคฐเคพ",
426
- "logged_in_as": "โœ… เคฒเฅ‰เค—เคฟเคจ เค•เฅ‡เคฒเฅ‡ เค†เคนเฅ‡:",
427
- "logout_btn": "เคฒเฅ‰เค—เค†เค‰เคŸ",
428
- "footer": "๐ŸŒพ เคถเฅ‡เคคเค•เคฐเฅ€ เคธเคนเค•เคพเคฐ v4.0 - เคธเคฐเฅเคต เคถเฅ‡เคคเค•เคฐเฅเคฏเคพเค‚เคธเคพเค เฅ€ | ๐Ÿšœ เคธเฅ‹เคชเฅ‡, เคธเคฐเคฒ เค†เคฃเคฟ เคตเคฟเคจเคพเคฎเฅ‚เคฒเฅเคฏ",
429
- "kharif": "เค–เคฐเฅ€เคซ",
430
- "rabi": "เคฐเคฌเฅ€",
431
- "summer": "เค‰เคจเฅ๏ฟฝ๏ฟฝ๏ฟฝเคพเคณเคพ",
432
- "wheat": "เค—เคนเฅ‚",
433
- "rice": "เคคเคพเค‚เคฆเฅ‚เคณ",
434
- "cotton": "เค•เคชเคพเคธ",
435
- "sugarcane": "เคŠเคธ",
436
- "potato": "เคฌเคŸเคพเคŸเคพ",
437
- "tomato": "เคŸเคฎเคพเคŸเคฐ",
438
- "onion": "เค•เคพเค‚เคฆเคพ",
439
- "corn": "เคฎเค•เฅเค•เคพ",
440
- }
441
- }
442
-
443
- def t(key):
444
- """Translate a key based on user's language preference"""
445
- lang = st.session_state.get("language", "Hindi")
446
- return TRANSLATIONS.get(lang, TRANSLATIONS["Hindi"]).get(key, key)
447
-
448
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
449
  # STREAMLIT PAGE CONFIG
450
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
451
 
452
  st.set_page_config(
453
- page_title="๐ŸŒพ Farmer Copilot v4.0",
454
  page_icon="๐Ÿšœ",
455
  layout="wide",
456
  initial_sidebar_state="expanded"
457
  )
458
 
459
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
460
- # CUSTOM CSS
461
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
462
-
463
  def inject_css():
464
  st.markdown("""
465
  <style>
@@ -480,27 +95,13 @@ def inject_css():
480
  color: white;
481
  font-weight: bold;
482
  border: none;
483
- border-radius: 12px;
484
- padding: 15px 30px;
485
- font-size: 18px;
486
  transition: all 0.3s ease;
487
- cursor: pointer;
488
  }
489
  .stButton > button:hover {
490
  box-shadow: 0 4px 12px rgba(45, 145, 94, 0.4);
491
- transform: scale(1.05);
492
- }
493
- .big-emoji {
494
- font-size: 60px;
495
- text-align: center;
496
- margin: 20px 0;
497
- }
498
- .metric-card {
499
- background: linear-gradient(135deg, #32B899 0%, #2180A0 100%);
500
- color: white;
501
- padding: 20px;
502
- border-radius: 12px;
503
- box-shadow: 0 4px 6px rgba(0,0,0,0.1);
504
  }
505
  </style>
506
  """, unsafe_allow_html=True)
@@ -508,47 +109,7 @@ def inject_css():
508
  inject_css()
509
 
510
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
511
- # FEATURE 1: VOICE I/O
512
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
513
-
514
- def voice_input(language="en-IN"):
515
- """Capture voice input from microphone"""
516
- if not VOICE_AVAILABLE:
517
- return None, "Voice feature not available"
518
-
519
- try:
520
- recognizer = sr.Recognizer()
521
- with sr.Microphone() as source:
522
- st.info(t("listening"))
523
- recognizer.adjust_for_ambient_noise(source, duration=1)
524
- audio = recognizer.listen(source, timeout=10)
525
-
526
- text = recognizer.recognize_google(audio, language=language)
527
- return text, None
528
- except Exception as e:
529
- return None, f"Error: {str(e)}"
530
-
531
- def voice_output(text, language="en"):
532
- """Convert text to speech"""
533
- if not VOICE_AVAILABLE:
534
- return
535
-
536
- try:
537
- tts = gTTS(text=text, lang=language, slow=True)
538
- audio_file = "response.mp3"
539
- tts.save(audio_file)
540
-
541
- with open(audio_file, "rb") as f:
542
- audio_bytes = f.read()
543
- st.audio(audio_bytes, format="audio/mp3")
544
-
545
- if os.path.exists(audio_file):
546
- os.remove(audio_file)
547
- except Exception as e:
548
- st.error(f"Voice error: {str(e)}")
549
-
550
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
551
- # FEATURE 2: IMAGE RECOGNITION
552
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
553
 
554
  @st.cache_resource
@@ -581,11 +142,11 @@ def analyze_plant_disease(image_file):
581
 
582
  predictions = model.predict(image_array)
583
  disease_map = {
584
- 0: "Early Blight - Treatment: Spray fungicide",
585
- 1: "Late Blight - Treatment: Spray mancozeb",
586
- 2: "Powdery Mildew - Treatment: Apply sulfur powder",
587
- 3: "Leaf Spot - Treatment: Spray neem oil",
588
- 4: "Healthy Plant - No disease!"
589
  }
590
 
591
  predicted_disease_idx = np.argmax(predictions[0])
@@ -602,15 +163,63 @@ def analyze_plant_disease(image_file):
602
  return None, f"Error: {str(e)}"
603
 
604
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
605
- # FEATURE 3: DATABASES
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
607
 
608
  def init_farm_database():
609
  """Initialize SQLite database for farm data"""
610
  conn = sqlite3.connect('farm_data.db')
611
  c = conn.cursor()
 
612
  c.execute('''CREATE TABLE IF NOT EXISTS yields
613
- (id INTEGER PRIMARY KEY, date TEXT, crop TEXT, area REAL, yield REAL, location TEXT)''')
 
 
 
 
 
 
614
  conn.commit()
615
  conn.close()
616
 
@@ -618,19 +227,235 @@ def save_farm_data(crop, area, yield_amount, location):
618
  """Save yield data to database"""
619
  conn = sqlite3.connect('farm_data.db')
620
  c = conn.cursor()
 
621
  date = datetime.now().strftime("%Y-%m-%d")
622
  c.execute('INSERT INTO yields VALUES (NULL, ?, ?, ?, ?, ?)',
623
  (date, crop, area, yield_amount, location))
 
624
  conn.commit()
625
  conn.close()
626
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
627
  def init_soil_database():
628
  """Initialize soil data database"""
629
  conn = sqlite3.connect('soil_data.db')
630
  c = conn.cursor()
 
631
  c.execute('''CREATE TABLE IF NOT EXISTS soil_tests
632
- (id INTEGER PRIMARY KEY, date TEXT, location TEXT, pH REAL, nitrogen INTEGER,
633
- phosphorus INTEGER, potassium INTEGER, organic_matter REAL, moisture REAL)''')
 
 
 
 
 
 
 
 
634
  conn.commit()
635
  conn.close()
636
 
@@ -638,9 +463,13 @@ def save_soil_test(location, pH, nitrogen, phosphorus, potassium, organic_matter
638
  """Save soil test results"""
639
  conn = sqlite3.connect('soil_data.db')
640
  c = conn.cursor()
 
641
  date = datetime.now().strftime("%Y-%m-%d")
642
- c.execute('''INSERT INTO soil_tests VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?)''',
 
 
643
  (date, location, pH, nitrogen, phosphorus, potassium, organic_matter, moisture))
 
644
  conn.commit()
645
  conn.close()
646
 
@@ -649,33 +478,37 @@ def get_soil_recommendations(pH, nitrogen, phosphorus, potassium):
649
  recommendations = []
650
 
651
  if pH < 6.0:
652
- recommendations.append(t("acidic_soil"))
653
  elif pH > 8.0:
654
- recommendations.append(t("alkaline_soil"))
655
  else:
656
- recommendations.append(t("ideal_ph"))
657
 
658
  if nitrogen < 200:
659
- recommendations.append(t("low_nitrogen"))
660
  elif nitrogen > 500:
661
- recommendations.append(t("high_nitrogen"))
662
  else:
663
- recommendations.append(t("ideal_nitrogen"))
664
 
665
  if phosphorus < 10:
666
- recommendations.append(t("low_phosphorus"))
 
 
667
  else:
668
- recommendations.append(t("ideal_phosphorus"))
669
 
670
  if potassium < 100:
671
- recommendations.append(t("low_potassium"))
 
 
672
  else:
673
- recommendations.append(t("ideal_potassium"))
674
 
675
  return recommendations
676
 
677
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
678
- # FEATURE 4: ML YIELD PREDICTION
679
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
680
 
681
  def train_yield_model():
@@ -684,7 +517,7 @@ def train_yield_model():
684
  return None, None
685
 
686
  X_train = np.array([
687
- [25, 80, 250, 6.5, 2.5],
688
  [28, 70, 200, 6.5, 3.0],
689
  [22, 85, 300, 6.8, 2.8],
690
  [26, 75, 250, 7.0, 3.2],
@@ -735,7 +568,108 @@ def predict_yield(temperature, humidity, rainfall, pH, organic_matter):
735
  return max(0, yield_pred)
736
 
737
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
738
- # FEATURE 5: WEATHER & ALERTS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739
  # โ•โ•โ•โ•โ•โ•โ•๏ฟฝ๏ฟฝโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
740
 
741
  def get_weather_data(location: str) -> Optional[Dict]:
@@ -783,127 +717,36 @@ def get_current_season() -> str:
783
  """Get current agricultural season"""
784
  month = datetime.now().month
785
  if month in [6, 7, 8, 9]:
786
- return t("kharif")
787
  elif month in [10, 11, 12, 1, 2]:
788
- return t("rabi")
789
  else:
790
- return t("summer")
791
-
792
- def check_weather_alerts(weather_data):
793
- """Check weather for farming alerts"""
794
- alerts = []
795
-
796
- if weather_data:
797
- temp = weather_data.get('temperature', 0)
798
- humidity = weather_data.get('humidity', 0)
799
-
800
- if temp < 0:
801
- alerts.append({'message': t("frost_risk"), 'severity': 'HIGH'})
802
- elif temp > 40:
803
- alerts.append({'message': t("high_temp"), 'severity': 'HIGH'})
804
-
805
- if humidity > 85:
806
- alerts.append({'message': t("high_humidity"), 'severity': 'MEDIUM'})
807
-
808
- return alerts
809
-
810
- def display_alerts():
811
- """Display all alerts in sidebar"""
812
- with st.sidebar:
813
- st.markdown(f"### {t('alerts')}")
814
-
815
- all_alerts = []
816
-
817
- try:
818
- weather = get_weather_data(st.session_state.location)
819
- all_alerts.extend(check_weather_alerts(weather))
820
- except:
821
- pass
822
-
823
- if all_alerts:
824
- for alert in all_alerts:
825
- if alert['severity'] == 'HIGH':
826
- st.error(alert['message'])
827
- elif alert['severity'] == 'MEDIUM':
828
- st.warning(alert['message'])
829
- else:
830
- st.info(alert['message'])
831
- else:
832
- st.success(t("all_conditions_normal"))
833
-
834
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
835
- # FEATURE 6: MARKET PRICES
836
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
837
 
838
- @st.cache_data(ttl=3600)
839
- def get_live_market_prices():
840
- """Get live market prices"""
841
- return {
842
- t("wheat"): 2250,
843
- t("rice"): 2650,
844
- t("cotton"): 5800,
845
- t("sugarcane"): 295,
846
- t("potato"): 1650,
847
- t("tomato"): 1350,
848
- t("onion"): 1950,
849
- t("corn"): 2000
850
  }
851
-
852
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
853
- # FEATURE 7: USER AUTHENTICATION
854
- # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
855
-
856
- def init_user_database():
857
- """Initialize user database"""
858
- conn = sqlite3.connect('users.db')
859
- c = conn.cursor()
860
- c.execute('''CREATE TABLE IF NOT EXISTS users
861
- (id INTEGER PRIMARY KEY, username TEXT UNIQUE, password TEXT, email TEXT, location TEXT, created_date TEXT)''')
862
- conn.commit()
863
- conn.close()
864
-
865
- def hash_password(password):
866
- """Hash password"""
867
- return hashlib.sha256(password.encode()).hexdigest()
868
-
869
- def register_user(username, password, email, location):
870
- """Register new user"""
871
- try:
872
- conn = sqlite3.connect('users.db')
873
- c = conn.cursor()
874
- hashed_pwd = hash_password(password)
875
- date = datetime.now().strftime("%Y-%m-%d")
876
- c.execute('INSERT INTO users VALUES (NULL, ?, ?, ?, ?, ?)',
877
- (username, hashed_pwd, email, location, date))
878
- conn.commit()
879
- conn.close()
880
- return True, "User registered successfully!"
881
- except sqlite3.IntegrityError:
882
- return False, "Username already exists"
883
- except Exception as e:
884
- return False, str(e)
885
-
886
- def login_user(username, password):
887
- """Login user"""
888
- try:
889
- conn = sqlite3.connect('users.db')
890
- c = conn.cursor()
891
- hashed_pwd = hash_password(password)
892
- c.execute('SELECT * FROM users WHERE username=? AND password=?', (username, hashed_pwd))
893
- user = c.fetchone()
894
- conn.close()
895
- return (True, user) if user else (False, "Invalid credentials")
896
- except Exception as e:
897
- return False, str(e)
898
 
899
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
900
  # SESSION STATE INITIALIZATION
901
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
902
 
 
 
903
  if "location" not in st.session_state:
904
- st.session_state.location = "เคฎเคนเคพเคฐเคพเคทเฅเคŸเฅเคฐ"
905
  if "language" not in st.session_state:
906
- st.session_state.language = "Hindi"
 
 
 
 
907
  if "user_authenticated" not in st.session_state:
908
  st.session_state.user_authenticated = False
909
  st.session_state.username = None
@@ -914,28 +757,38 @@ if 'db_initialized' not in st.session_state:
914
  st.session_state.db_initialized = True
915
 
916
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
917
- # SIDEBAR - LANGUAGE SELECTION
918
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
919
 
920
  with st.sidebar:
921
- st.markdown(f"### {t('settings')}")
922
 
923
  location = st.selectbox(
924
- t("location"),
925
- ["เคฎเคนเคพเคฐเคพเคทเฅเคŸเฅเคฐ", "เคชเค‚เคœเคพเคฌ", "เคนเคฐเคฟเคฏเคพเคฃเคพ", "เค‰เคคเฅเคคเคฐ เคชเฅเคฐเคฆเฅ‡เคถ", "เค•เคฐเฅเคจเคพเคŸเค•", "เคฐเคพเคœเคธเฅเคฅเคพเคจ"],
926
- key="sidebar_location_key"
927
  )
928
  st.session_state.location = location
929
 
930
  language = st.selectbox(
931
- t("language"),
932
- ["Hindi", "English", "Marathi"],
933
- index=["Hindi", "English", "Marathi"].index(st.session_state.language) if st.session_state.language in ["Hindi", "English", "Marathi"] else 0,
934
- key="sidebar_language_key"
935
  )
 
936
 
937
- if language != st.session_state.language:
938
- st.session_state.language = language
 
 
 
 
 
 
 
 
 
 
939
  st.rerun()
940
 
941
  st.divider()
@@ -945,280 +798,253 @@ with st.sidebar:
945
  # MAIN CONTENT
946
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
947
 
948
- st.markdown(f"# {t('title')}")
949
- st.markdown(f"### {t('subtitle')}")
950
  st.divider()
951
 
952
  # DEFINE TABS WITH UNIQUE KEYS
953
  tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8, tab9, tab10, tab11, tab12 = st.tabs([
954
- t("voice_assistant"), t("weather"), t("market"), t("crops"),
955
- t("pests"), t("irrigation"), t("analytics"), t("disease"),
956
- t("other"), t("soil"), t("yield"), t("profile")
957
  ])
958
 
959
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
960
- # TAB 1: VOICE INTERACTION
961
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
962
 
963
  with tab1:
964
- st.markdown(t("speak_with_voice"))
965
- st.markdown(t("what_you_want"))
966
-
967
- col1, col2, col3 = st.columns(3)
968
 
969
- with col1:
970
- st.markdown("<div class='big-emoji'>๐ŸŒง๏ธ</div>", unsafe_allow_html=True)
971
- if st.button(t("rainfall_info"), key="voice_rainfall_btn", use_container_width=True):
972
- with st.spinner("..."):
973
- weather = get_weather_data(st.session_state.location)
974
- if weather:
975
- msg = f"Temperature {weather['temperature']:.0f}ยฐC, Humidity {weather['humidity']}%"
976
- st.success(msg)
977
- if VOICE_AVAILABLE:
978
- lang_code = "hi" if st.session_state.language == "Hindi" else "mr" if st.session_state.language == "Marathi" else "en"
979
- voice_output(msg, language=lang_code)
980
- else:
981
- st.info(t("weather_unavailable"))
982
-
983
- with col2:
984
- st.markdown("<div class='big-emoji'>๐Ÿ›</div>", unsafe_allow_html=True)
985
- if st.button(t("pest_problem"), key="voice_pest_btn", use_container_width=True):
986
- st.info(t("upload_photo_disease"))
987
- if VOICE_AVAILABLE:
988
- lang_code = "hi" if st.session_state.language == "Hindi" else "mr" if st.session_state.language == "Marathi" else "en"
989
- voice_output(t("go_disease_tab"), language=lang_code)
990
-
991
- with col3:
992
- st.markdown("<div class='big-emoji'>๐Ÿ’ฑ</div>", unsafe_allow_html=True)
993
- if st.button(t("market_prices"), key="voice_market_btn", use_container_width=True):
994
- prices = get_live_market_prices()
995
- price_list = ", ".join([f"{crop}: โ‚น{price}" for crop, price in list(prices.items())[:3]])
996
- st.success(price_list)
997
- if VOICE_AVAILABLE:
998
- lang_code = "hi" if st.session_state.language == "Hindi" else "mr" if st.session_state.language == "Marathi" else "en"
999
- voice_output(price_list, language=lang_code)
1000
-
1001
- st.divider()
1002
 
1003
- col1, col2 = st.columns(2)
1004
 
1005
- with col1:
1006
- st.markdown(f"<h3 style='text-align: center;'>{t('speak_question')}</h3>", unsafe_allow_html=True)
1007
- if st.button(t("microphone_on"), key="voice_listen_btn", use_container_width=True):
1008
- if VOICE_AVAILABLE:
1009
- lang_code = "hi-IN" if st.session_state.language == "Hindi" else "mr-IN" if st.session_state.language == "Marathi" else "en-IN"
1010
- text, error = voice_input(language=lang_code)
1011
- if error:
1012
- st.error(error)
1013
- elif text:
1014
- st.success(f"{t('you_said')} {text}")
 
 
 
 
 
 
 
 
1015
 
1016
- with col2:
1017
- st.markdown(f"<h3 style='text-align: center;'>{t('hear_answer')}</h3>", unsafe_allow_html=True)
1018
- if st.button("๐Ÿ”Š Replay", key="voice_replay_btn", use_container_width=True):
1019
- if VOICE_AVAILABLE:
1020
- lang_code = "hi" if st.session_state.language == "Hindi" else "mr" if st.session_state.language == "Marathi" else "en"
1021
- voice_output("Thank you for using Farmer Copilot", language=lang_code)
 
 
 
 
1022
 
1023
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1024
  # TAB 2: WEATHER
1025
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1026
 
1027
  with tab2:
1028
- st.markdown(t("weather_info"))
1029
 
1030
- if st.button(t("refresh_weather"), key="weather_refresh_btn", use_container_width=True):
1031
- with st.spinner(t("loading")):
1032
  weather = get_weather_data(st.session_state.location)
1033
  if weather:
1034
- col1, col2, col3, col4 = st.columns(4)
1035
- col1.metric(t("temperature"), f"{weather['temperature']:.1f}ยฐC")
1036
- col2.metric(t("humidity"), f"{weather['humidity']}%")
1037
- col3.metric(t("wind"), f"{weather['wind_speed']:.1f} m/s")
1038
- col4.metric(t("location"), weather['location'])
1039
- else:
1040
- st.warning(t("weather_unavailable"))
 
 
1041
 
1042
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1043
  # TAB 3: MARKET PRICES
1044
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1045
 
1046
  with tab3:
1047
- st.markdown(t("market_prices_title"))
1048
 
1049
- if st.button(t("refresh_prices"), key="market_refresh_btn", use_container_width=True):
1050
  live_prices = get_live_market_prices()
1051
  if live_prices:
1052
- cols = st.columns(2)
1053
  crops_list = list(live_prices.keys())
1054
 
1055
- for idx, crop in enumerate(crops_list):
1056
- col = cols[idx % 2]
1057
- col.metric(crop, f"โ‚น{live_prices[crop]}{t('per_quintal')}")
 
 
 
 
1058
 
1059
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1060
- # TAB 4-7: PLACEHOLDER TABS
1061
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1062
 
1063
  with tab4:
1064
- st.markdown(t("crop_suggestions"))
1065
- st.info(t("best_crops"))
1066
- st.write(f"{t('current_season')} {get_current_season()}")
1067
 
1068
  with tab5:
1069
- st.markdown(t("pest_management"))
1070
- st.info(t("pest_info"))
1071
 
1072
  with tab6:
1073
- st.markdown(t("irrigation_management"))
1074
- st.info(t("irrigation_info"))
1075
 
1076
  with tab7:
1077
- st.markdown(t("farm_analytics"))
1078
- st.info(t("analytics_info"))
1079
 
1080
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1081
- # TAB 8: IMAGE RECOGNITION
1082
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1083
 
1084
  with tab8:
1085
- st.markdown(t("disease_detection"))
1086
-
1087
- uploaded_file = st.file_uploader(t("upload_leaf"), type=['jpg', 'jpeg', 'png'], key="image_uploader_key")
1088
 
1089
- if uploaded_file:
1090
- col1, col2 = st.columns([2, 1])
1091
-
1092
- with col1:
1093
- image = Image.open(uploaded_file)
1094
- st.image(image, caption=t("your_photo"), use_column_width=True)
1095
-
1096
- with col2:
1097
- if st.button(t("analyze"), key="image_analyze_btn"):
1098
- if IMAGE_RECOGNITION_AVAILABLE:
1099
- result, error = analyze_plant_disease(uploaded_file)
1100
- if error:
1101
- st.error(error)
1102
- else:
1103
- st.success(t("analysis_complete"))
1104
- st.metric(t("disease"), result['disease'].split('-')[0])
1105
- st.metric(t("confidence"), f"{result['confidence']:.1f}%")
1106
- st.metric(t("severity"), result['severity'])
1107
- else:
1108
- st.warning(t("image_recognition_unavailable"))
1109
 
1110
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1111
- # TAB 9: MISC
1112
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1113
 
1114
  with tab9:
1115
- st.markdown(f"### ๐ŸŽค {t('other')}")
1116
- st.info("Additional voice options")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1117
 
1118
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1119
- # TAB 10: SOIL HEALTH
1120
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1121
 
1122
  with tab10:
1123
- st.markdown(t("soil_check"))
1124
 
1125
  col1, col2, col3 = st.columns(3)
1126
  with col1:
1127
- pH = st.slider(t("soil_ph"), 4.0, 9.0, 6.5, key="soil_pH_slider_tab10")
1128
- nitrogen = st.slider(t("nitrogen"), 0, 1000, 250, key="soil_nitrogen_slider_tab10")
1129
  with col2:
1130
- phosphorus = st.slider(t("phosphorus"), 0, 100, 20, key="soil_phosphorus_slider_tab10")
1131
- potassium = st.slider(t("potassium"), 0, 500, 150, key="soil_potassium_slider_tab10")
1132
  with col3:
1133
- organic_matter = st.slider(t("organic_matter"), 0.0, 10.0, 2.5, key="soil_organic_slider_tab10")
1134
- moisture = st.slider(t("moisture"), 0.0, 50.0, 25.0, key="soil_moisture_slider_tab10")
1135
 
1136
- if st.button(t("save_soil_test"), key="soil_save_btn_tab10", use_container_width=True):
1137
  save_soil_test(st.session_state.location, pH, nitrogen, phosphorus, potassium, organic_matter, moisture)
1138
- st.success(t("saved"))
1139
 
1140
  recommendations = get_soil_recommendations(pH, nitrogen, phosphorus, potassium)
1141
- st.markdown(t("recommendations"))
1142
  for rec in recommendations:
1143
  st.markdown(rec)
1144
 
1145
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1146
- # TAB 11: YIELD PREDICTION
1147
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1148
 
1149
  with tab11:
1150
- st.markdown(t("yield_prediction"))
1151
 
1152
  col1, col2, col3 = st.columns(3)
1153
  with col1:
1154
- temp = st.slider(t("temp_celsius"), 0, 45, 25, key="yield_temp_slider_tab11")
1155
- humidity = st.slider(t("humidity_percent"), 0, 100, 70, key="yield_humidity_slider_tab11")
1156
  with col2:
1157
- rainfall = st.slider(t("rainfall_mm"), 0, 500, 250, key="yield_rainfall_slider_tab11")
1158
- pH = st.slider(t("soil_ph"), 4.0, 9.0, 6.8, key="yield_pH_slider_tab11")
1159
  with col3:
1160
- org_matter = st.slider(t("organic_matter"), 0.0, 10.0, 2.5, key="yield_orgmatter_slider_tab11")
1161
 
1162
- if st.button(t("predict_yield"), key="yield_predict_btn_tab11", use_container_width=True):
1163
  yield_pred = predict_yield(temp, humidity, rainfall, pH, org_matter)
1164
- st.success(f"{t('estimated_yield')} {yield_pred:.1f} {t('quintal_hectare')}")
1165
-
1166
- if yield_pred > 25:
1167
- st.info(t("high_yield"))
1168
- elif yield_pred > 20:
1169
- st.info(t("average_yield"))
1170
- else:
1171
- st.warning(t("low_yield"))
1172
 
1173
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1174
- # TAB 12: USER PROFILE
1175
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1176
 
1177
  with tab12:
1178
- st.markdown(t("profile_settings"))
1179
 
1180
  if not st.session_state.user_authenticated:
1181
- auth_choice = st.radio(t("choose_option"), [t("login"), t("register")], key="auth_choice_radio_tab12")
1182
 
1183
- if auth_choice == t("login"):
1184
- st.subheader(t("login_title"))
1185
-
1186
- username = st.text_input(t("username"), key="login_username_tab12")
1187
- password = st.text_input(t("password"), type="password", key="login_password_tab12")
1188
 
1189
- if st.button(t("login_btn"), key="login_btn_tab12", use_container_width=True):
1190
  success, result = login_user(username, password)
1191
-
1192
  if success:
1193
  st.session_state.user_authenticated = True
1194
  st.session_state.username = username
1195
- st.success(t("login_success"))
1196
  st.rerun()
1197
  else:
1198
- st.error(t("invalid_credentials"))
1199
-
1200
  else:
1201
- st.subheader(t("register_title"))
1202
-
1203
- new_username = st.text_input(t("username"), key="register_username_tab12")
1204
- new_email = st.text_input(t("email"), key="register_email_tab12")
1205
- new_password = st.text_input(t("password"), type="password", key="register_password_tab12")
1206
 
1207
- if st.button(t("register_btn"), key="register_btn_tab12", use_container_width=True):
1208
  success, msg = register_user(new_username, new_password, new_email, st.session_state.location)
1209
-
1210
- if success:
1211
- st.success(t("registration_success"))
1212
- else:
1213
- st.error(f"โŒ {msg}")
1214
-
1215
  else:
1216
- st.success(f"{t('logged_in_as')} **{st.session_state.username}**")
1217
-
1218
- if st.button(t("logout_btn"), key="logout_btn_tab12", use_container_width=True):
1219
  st.session_state.user_authenticated = False
1220
- st.session_state.username = None
1221
  st.rerun()
1222
 
1223
  st.divider()
1224
- st.markdown(f"<div style='text-align: center'><p>{t('footer')}</p></div>", unsafe_allow_html=True)
 
3
  import numpy as np
4
  from datetime import datetime, timedelta
5
  import logging
 
6
  import requests
7
+ from typing import Optional, Dict, List, Any
8
  import json
9
  from io import BytesIO
10
  from PIL import Image
 
13
  import sqlite3
14
  import hashlib
15
 
16
+ # OpenAI Integration
17
+ try:
18
+ from openai import OpenAI
19
+ OPENAI_AVAILABLE = True
20
+ except ImportError:
21
+ OPENAI_AVAILABLE = False
22
 
23
  # Image Recognition
24
  try:
 
64
  logging.basicConfig(level=logging.INFO)
65
  logger = logging.getLogger(__name__)
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
68
  # STREAMLIT PAGE CONFIG
69
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
70
 
71
  st.set_page_config(
72
+ page_title="๐ŸŒพ Farmer Copilot v3.0 - Complete",
73
  page_icon="๐Ÿšœ",
74
  layout="wide",
75
  initial_sidebar_state="expanded"
76
  )
77
 
 
 
 
 
78
  def inject_css():
79
  st.markdown("""
80
  <style>
 
95
  color: white;
96
  font-weight: bold;
97
  border: none;
98
+ border-radius: 8px;
99
+ padding: 10px 24px;
 
100
  transition: all 0.3s ease;
 
101
  }
102
  .stButton > button:hover {
103
  box-shadow: 0 4px 12px rgba(45, 145, 94, 0.4);
104
+ transform: translateY(-2px);
 
 
 
 
 
 
 
 
 
 
 
 
105
  }
106
  </style>
107
  """, unsafe_allow_html=True)
 
109
  inject_css()
110
 
111
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
112
+ # FEATURE 1: IMAGE RECOGNITION
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
114
 
115
  @st.cache_resource
 
142
 
143
  predictions = model.predict(image_array)
144
  disease_map = {
145
+ 0: "Early Blight - Use fungicide",
146
+ 1: "Late Blight - Spray mancozeb",
147
+ 2: "Powdery Mildew - Apply sulfur",
148
+ 3: "Leaf Spot - Spray neem oil",
149
+ 4: "Healthy Plant - No disease"
150
  }
151
 
152
  predicted_disease_idx = np.argmax(predictions[0])
 
163
  return None, f"Error: {str(e)}"
164
 
165
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
166
+ # FEATURE 2: VOICE I/O
167
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
168
+
169
+ def voice_input():
170
+ """Capture voice input from microphone"""
171
+ if not VOICE_AVAILABLE:
172
+ return None, "Voice feature not available"
173
+
174
+ try:
175
+ recognizer = sr.Recognizer()
176
+ with sr.Microphone() as source:
177
+ st.info("๐ŸŽ™๏ธ Listening...")
178
+ recognizer.adjust_for_ambient_noise(source, duration=1)
179
+ audio = recognizer.listen(source, timeout=10)
180
+
181
+ text = recognizer.recognize_google(audio, language='en-IN')
182
+ return text, None
183
+
184
+ except Exception as e:
185
+ return None, f"Error: {str(e)}"
186
+
187
+ def voice_output(text, language="en"):
188
+ """Convert text to speech"""
189
+ if not VOICE_AVAILABLE:
190
+ return
191
+
192
+ try:
193
+ tts = gTTS(text=text, lang=language, slow=False)
194
+ audio_file = "response.mp3"
195
+ tts.save(audio_file)
196
+
197
+ with open(audio_file, "rb") as f:
198
+ audio_bytes = f.read()
199
+ st.audio(audio_bytes, format="audio/mp3")
200
+
201
+ if os.path.exists(audio_file):
202
+ os.remove(audio_file)
203
+ except Exception as e:
204
+ st.error(f"Voice error: {str(e)}")
205
+
206
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
207
+ # FEATURE 3: HISTORICAL DATA TRACKING
208
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
209
 
210
  def init_farm_database():
211
  """Initialize SQLite database for farm data"""
212
  conn = sqlite3.connect('farm_data.db')
213
  c = conn.cursor()
214
+
215
  c.execute('''CREATE TABLE IF NOT EXISTS yields
216
+ (id INTEGER PRIMARY KEY,
217
+ date TEXT,
218
+ crop TEXT,
219
+ area REAL,
220
+ yield REAL,
221
+ location TEXT)''')
222
+
223
  conn.commit()
224
  conn.close()
225
 
 
227
  """Save yield data to database"""
228
  conn = sqlite3.connect('farm_data.db')
229
  c = conn.cursor()
230
+
231
  date = datetime.now().strftime("%Y-%m-%d")
232
  c.execute('INSERT INTO yields VALUES (NULL, ?, ?, ?, ?, ?)',
233
  (date, crop, area, yield_amount, location))
234
+
235
  conn.commit()
236
  conn.close()
237
 
238
+ def get_historical_yields(crop=None, days=90):
239
+ """Get historical yield data"""
240
+ conn = sqlite3.connect('farm_data.db')
241
+
242
+ if crop:
243
+ df = pd.read_sql_query(
244
+ f"SELECT * FROM yields WHERE crop='{crop}' ORDER BY date DESC LIMIT 10",
245
+ conn
246
+ )
247
+ else:
248
+ df = pd.read_sql_query(
249
+ f"SELECT * FROM yields ORDER BY date DESC LIMIT 10",
250
+ conn
251
+ )
252
+
253
+ conn.close()
254
+ return df
255
+
256
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
257
+ # FEATURE 4: DATA EXPORT
258
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
259
+
260
+ def export_to_csv(data_dict, filename="farm_report"):
261
+ """Export data to CSV"""
262
+ df = pd.DataFrame(data_dict)
263
+ csv_buffer = BytesIO()
264
+ df.to_csv(csv_buffer, index=False)
265
+ csv_buffer.seek(0)
266
+ return csv_buffer, f"{filename}.csv"
267
+
268
+ def export_to_excel(data_dict, filename="farm_report"):
269
+ """Export data to Excel"""
270
+ df = pd.DataFrame(data_dict)
271
+ excel_buffer = BytesIO()
272
+
273
+ try:
274
+ with pd.ExcelWriter(excel_buffer, engine='openpyxl') as writer:
275
+ df.to_excel(writer, sheet_name='Farm Data', index=False)
276
+ except:
277
+ df.to_excel(excel_buffer, sheet_name='Farm Data', index=False)
278
+
279
+ excel_buffer.seek(0)
280
+ return excel_buffer, f"{filename}.xlsx"
281
+
282
+ def export_to_pdf(report_text, filename="farm_report"):
283
+ """Export report to PDF"""
284
+ if not EXPORT_AVAILABLE:
285
+ return None, None
286
+
287
+ pdf_buffer = BytesIO()
288
+ c = canvas.Canvas(pdf_buffer, pagesize=letter)
289
+
290
+ width, height = letter
291
+ y_position = height - 50
292
+
293
+ c.setFont("Helvetica-Bold", 16)
294
+ c.drawString(50, y_position, "Farmer Copilot Report")
295
+ y_position -= 30
296
+
297
+ c.setFont("Helvetica", 10)
298
+ for line in report_text.split('\n'):
299
+ if y_position < 50:
300
+ c.showPage()
301
+ y_position = height - 50
302
+ c.drawString(50, y_position, line[:80])
303
+ y_position -= 15
304
+
305
+ c.save()
306
+ pdf_buffer.seek(0)
307
+ return pdf_buffer, f"{filename}.pdf"
308
+
309
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
310
+ # FEATURE 5: SMART NOTIFICATIONS
311
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
312
+
313
+ def check_weather_alerts(weather_data):
314
+ """Check weather for farming alerts"""
315
+ alerts = []
316
+
317
+ if weather_data:
318
+ temp = weather_data.get('temperature', 0)
319
+ humidity = weather_data.get('humidity', 0)
320
+
321
+ if temp < 0:
322
+ alerts.append({'message': 'โ„๏ธ Frost Risk! Protect delicate crops', 'severity': 'HIGH'})
323
+ elif temp > 40:
324
+ alerts.append({'message': '๐Ÿ”ฅ High Temperature! Increase irrigation', 'severity': 'HIGH'})
325
+
326
+ if humidity > 85:
327
+ alerts.append({'message': '๐Ÿฆ  High Humidity! Watch for fungal diseases', 'severity': 'MEDIUM'})
328
+
329
+ return alerts
330
+
331
+ def display_alerts():
332
+ """Display all alerts in sidebar"""
333
+ with st.sidebar:
334
+ st.markdown("### ๐Ÿ”” Smart Alerts")
335
+
336
+ all_alerts = []
337
+
338
+ try:
339
+ weather = get_weather_data(st.session_state.location)
340
+ all_alerts.extend(check_weather_alerts(weather))
341
+ except:
342
+ pass
343
+
344
+ if all_alerts:
345
+ for alert in all_alerts:
346
+ if alert['severity'] == 'HIGH':
347
+ st.error(alert['message'])
348
+ elif alert['severity'] == 'MEDIUM':
349
+ st.warning(alert['message'])
350
+ else:
351
+ st.info(alert['message'])
352
+ else:
353
+ st.success("โœ… All conditions normal!")
354
+
355
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
356
+ # FEATURE 6: REAL-TIME MARKET PRICES
357
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
358
+
359
+ @st.cache_data(ttl=3600)
360
+ def get_live_market_prices():
361
+ """Get live market prices"""
362
+ return {
363
+ "Wheat": 2250, "Rice": 2650, "Cotton": 5800, "Sugarcane": 295,
364
+ "Potato": 1650, "Tomato": 1350, "Onion": 1950, "Corn": 2000
365
+ }
366
+
367
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
368
+ # FEATURE 7: USER AUTHENTICATION
369
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
370
+
371
+ def init_user_database():
372
+ """Initialize user database"""
373
+ conn = sqlite3.connect('users.db')
374
+ c = conn.cursor()
375
+
376
+ c.execute('''CREATE TABLE IF NOT EXISTS users
377
+ (id INTEGER PRIMARY KEY,
378
+ username TEXT UNIQUE,
379
+ password TEXT,
380
+ email TEXT,
381
+ location TEXT,
382
+ created_date TEXT)''')
383
+
384
+ conn.commit()
385
+ conn.close()
386
+
387
+ def hash_password(password):
388
+ """Hash password"""
389
+ return hashlib.sha256(password.encode()).hexdigest()
390
+
391
+ def register_user(username, password, email, location):
392
+ """Register new user"""
393
+ try:
394
+ conn = sqlite3.connect('users.db')
395
+ c = conn.cursor()
396
+
397
+ hashed_pwd = hash_password(password)
398
+ date = datetime.now().strftime("%Y-%m-%d")
399
+
400
+ c.execute('INSERT INTO users VALUES (NULL, ?, ?, ?, ?, ?)',
401
+ (username, hashed_pwd, email, location, date))
402
+
403
+ conn.commit()
404
+ conn.close()
405
+ return True, "User registered successfully!"
406
+ except sqlite3.IntegrityError:
407
+ return False, "Username already exists"
408
+ except Exception as e:
409
+ return False, str(e)
410
+
411
+ def login_user(username, password):
412
+ """Login user"""
413
+ try:
414
+ conn = sqlite3.connect('users.db')
415
+ c = conn.cursor()
416
+
417
+ hashed_pwd = hash_password(password)
418
+ c.execute('SELECT * FROM users WHERE username=? AND password=?',
419
+ (username, hashed_pwd))
420
+
421
+ user = c.fetchone()
422
+ conn.close()
423
+
424
+ return (True, user) if user else (False, "Invalid credentials")
425
+ except Exception as e:
426
+ return False, str(e)
427
+
428
+ def get_user_profile(username):
429
+ """Get user profile"""
430
+ conn = sqlite3.connect('users.db')
431
+ c = conn.cursor()
432
+
433
+ c.execute('SELECT * FROM users WHERE username=?', (username,))
434
+ user = c.fetchone()
435
+ conn.close()
436
+
437
+ return user
438
+
439
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
440
+ # FEATURE 8: SOIL HEALTH MONITORING
441
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
442
+
443
  def init_soil_database():
444
  """Initialize soil data database"""
445
  conn = sqlite3.connect('soil_data.db')
446
  c = conn.cursor()
447
+
448
  c.execute('''CREATE TABLE IF NOT EXISTS soil_tests
449
+ (id INTEGER PRIMARY KEY,
450
+ date TEXT,
451
+ location TEXT,
452
+ pH REAL,
453
+ nitrogen INTEGER,
454
+ phosphorus INTEGER,
455
+ potassium INTEGER,
456
+ organic_matter REAL,
457
+ moisture REAL)''')
458
+
459
  conn.commit()
460
  conn.close()
461
 
 
463
  """Save soil test results"""
464
  conn = sqlite3.connect('soil_data.db')
465
  c = conn.cursor()
466
+
467
  date = datetime.now().strftime("%Y-%m-%d")
468
+
469
+ c.execute('''INSERT INTO soil_tests
470
+ VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?)''',
471
  (date, location, pH, nitrogen, phosphorus, potassium, organic_matter, moisture))
472
+
473
  conn.commit()
474
  conn.close()
475
 
 
478
  recommendations = []
479
 
480
  if pH < 6.0:
481
+ recommendations.append("๐Ÿ”ด **Acidic Soil**: Apply lime (CaCO3)")
482
  elif pH > 8.0:
483
+ recommendations.append("๐Ÿ”ด **Alkaline Soil**: Apply sulfur or organic matter")
484
  else:
485
+ recommendations.append("โœ… **Ideal pH**: Between 6.5-7.5")
486
 
487
  if nitrogen < 200:
488
+ recommendations.append("๐ŸŸก **Low Nitrogen**: Apply NPK 20:20:0")
489
  elif nitrogen > 500:
490
+ recommendations.append("๐ŸŸก **High Nitrogen**: Reduce nitrogen fertilizer")
491
  else:
492
+ recommendations.append("โœ… **Optimal Nitrogen**: Good")
493
 
494
  if phosphorus < 10:
495
+ recommendations.append("๐ŸŸก **Low Phosphorus**: Apply DAP or SSP")
496
+ elif phosphorus > 30:
497
+ recommendations.append("๐ŸŸก **High Phosphorus**: No additional needed")
498
  else:
499
+ recommendations.append("โœ… **Optimal Phosphorus**: Good")
500
 
501
  if potassium < 100:
502
+ recommendations.append("๐ŸŸก **Low Potassium**: Apply KCl or MOP")
503
+ elif potassium > 300:
504
+ recommendations.append("๐ŸŸก **High Potassium**: Reduce fertilizer")
505
  else:
506
+ recommendations.append("โœ… **Optimal Potassium**: Good")
507
 
508
  return recommendations
509
 
510
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
511
+ # FEATURE 9: YIELD PREDICTION ML
512
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
513
 
514
  def train_yield_model():
 
517
  return None, None
518
 
519
  X_train = np.array([
520
+ [25, 80, 250, 20, 2.5],
521
  [28, 70, 200, 6.5, 3.0],
522
  [22, 85, 300, 6.8, 2.8],
523
  [26, 75, 250, 7.0, 3.2],
 
568
  return max(0, yield_pred)
569
 
570
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
571
+ # FEATURE 10: 7-DAY WEATHER FORECAST
572
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
573
+
574
+ def get_7day_forecast(location):
575
+ """Get 7-day weather forecast"""
576
+ try:
577
+ api_key = st.secrets.get("OPENWEATHER_API_KEY")
578
+
579
+ if not api_key:
580
+ return None
581
+
582
+ geo_url = "https://api.openweathermap.org/geo/1.0/direct"
583
+ geo_params = {"q": location, "limit": 1, "appid": api_key}
584
+ geo_resp = requests.get(geo_url, params=geo_params)
585
+
586
+ if not geo_resp.json():
587
+ return None
588
+
589
+ lat, lon = geo_resp.json()[0]['lat'], geo_resp.json()[0]['lon']
590
+
591
+ forecast_url = "https://api.openweathermap.org/data/2.5/forecast"
592
+ forecast_params = {
593
+ "lat": lat, "lon": lon, "appid": api_key,
594
+ "units": "metric", "cnt": 56
595
+ }
596
+
597
+ forecast_resp = requests.get(forecast_url, params=forecast_params)
598
+ forecast_data = forecast_resp.json()
599
+
600
+ forecast_list = []
601
+
602
+ for item in forecast_data['list'][::8]:
603
+ forecast_list.append({
604
+ 'Date': datetime.fromtimestamp(item['dt']).strftime("%a, %d %b"),
605
+ 'Temp': f"{item['main']['temp']:.1f}ยฐC",
606
+ 'Humidity': f"{item['main']['humidity']}%",
607
+ 'Condition': item['weather'][0]['main'],
608
+ 'Wind': f"{item['wind']['speed']:.1f} m/s"
609
+ })
610
+
611
+ return pd.DataFrame(forecast_list)
612
+
613
+ except Exception as e:
614
+ return None
615
+
616
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
617
+ # OPENAI SETUP
618
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
619
+
620
+ def initialize_openai():
621
+ """Initialize OpenAI client"""
622
+ if not OPENAI_AVAILABLE:
623
+ return None, "OpenAI library not installed"
624
+
625
+ api_key = None
626
+
627
+ try:
628
+ if hasattr(st, 'secrets') and "OPENAI_API_KEY" in st.secrets:
629
+ api_key = st.secrets["OPENAI_API_KEY"]
630
+ except:
631
+ pass
632
+
633
+ if not api_key:
634
+ api_key = os.environ.get("OPENAI_API_KEY")
635
+
636
+ if api_key and api_key.strip():
637
+ try:
638
+ client = OpenAI(api_key=api_key.strip())
639
+ return client, None
640
+ except Exception as e:
641
+ return None, f"Failed: {str(e)}"
642
+ else:
643
+ return None, "No API key found"
644
+
645
+ def get_ai_response(client, user_message: str, context: Dict, language: str = "English") -> str:
646
+ """Get response from OpenAI GPT"""
647
+ try:
648
+ if not client:
649
+ return "AI service not available."
650
+
651
+ system_prompt = "You are an expert agricultural advisor. Provide helpful farming advice."
652
+ location = context.get("location", "India")
653
+
654
+ messages = [
655
+ {"role": "system", "content": system_prompt},
656
+ {"role": "user", "content": f"Location: {location}\n\n{user_message}"}
657
+ ]
658
+
659
+ response = client.chat.completions.create(
660
+ model="gpt-3.5-turbo",
661
+ messages=messages,
662
+ temperature=0.7,
663
+ max_tokens=500
664
+ )
665
+
666
+ return response.choices[0].message.content
667
+
668
+ except Exception as e:
669
+ return f"Error: {str(e)}"
670
+
671
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
672
+ # HELPER FUNCTIONS
673
  # โ•โ•โ•โ•โ•โ•โ•๏ฟฝ๏ฟฝโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
674
 
675
  def get_weather_data(location: str) -> Optional[Dict]:
 
717
  """Get current agricultural season"""
718
  month = datetime.now().month
719
  if month in [6, 7, 8, 9]:
720
+ return "Kharif"
721
  elif month in [10, 11, 12, 1, 2]:
722
+ return "Rabi"
723
  else:
724
+ return "Summer"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
725
 
726
+ def get_market_prices(crop: str) -> Dict:
727
+ """Get market prices"""
728
+ prices = {
729
+ "Wheat": 2200, "Rice": 2500, "Cotton": 5500, "Sugarcane": 290,
730
+ "Potato": 1500, "Tomato": 1200, "Onion": 1800, "Corn": 1900
 
 
 
 
 
 
 
731
  }
732
+
733
+ base = prices.get(crop, 2000)
734
+ return {'crop': crop, 'price': base, 'min': base * 0.85, 'max': base * 1.15}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
735
 
736
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
737
  # SESSION STATE INITIALIZATION
738
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
739
 
740
+ if "messages" not in st.session_state:
741
+ st.session_state.messages = []
742
  if "location" not in st.session_state:
743
+ st.session_state.location = "Maharashtra"
744
  if "language" not in st.session_state:
745
+ st.session_state.language = "English"
746
+ if "openai_client" not in st.session_state:
747
+ client, error = initialize_openai()
748
+ st.session_state.openai_client = client
749
+ st.session_state.openai_error = error
750
  if "user_authenticated" not in st.session_state:
751
  st.session_state.user_authenticated = False
752
  st.session_state.username = None
 
757
  st.session_state.db_initialized = True
758
 
759
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
760
+ # SIDEBAR
761
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
762
 
763
  with st.sidebar:
764
+ st.markdown("### โš™๏ธ SETTINGS")
765
 
766
  location = st.selectbox(
767
+ "๐Ÿ“ Your Location",
768
+ ["Maharashtra", "Punjab", "Haryana", "Uttar Pradesh", "Karnataka"],
769
+ key="sidebar_location"
770
  )
771
  st.session_state.location = location
772
 
773
  language = st.selectbox(
774
+ "๐ŸŒ Language",
775
+ ["English", "Hindi", "Marathi"],
776
+ key="sidebar_language"
 
777
  )
778
+ st.session_state.language = language
779
 
780
+ st.divider()
781
+ st.markdown("### ๐Ÿค– AI STATUS")
782
+
783
+ if st.session_state.openai_client:
784
+ st.success("โœ… AI Enabled")
785
+ else:
786
+ st.error("โŒ AI Disabled")
787
+
788
+ if st.button("๐Ÿ”„ Reinitialize AI"):
789
+ client, error = initialize_openai()
790
+ st.session_state.openai_client = client
791
+ st.session_state.openai_error = error
792
  st.rerun()
793
 
794
  st.divider()
 
798
  # MAIN CONTENT
799
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
800
 
801
+ st.markdown("# ๐ŸŒพ FARMER COPILOT v3.0 - COMPLETE")
802
+ st.markdown("### AI Agricultural Intelligence Platform with 15 Features ๐Ÿšœ")
803
  st.divider()
804
 
805
  # DEFINE TABS WITH UNIQUE KEYS
806
  tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8, tab9, tab10, tab11, tab12 = st.tabs([
807
+ "๐Ÿ’ฌ AI Chat", "๐ŸŒค๏ธ Weather", "๐Ÿ’ฐ Market", "๐ŸŒฑ Crops",
808
+ "๐Ÿ› Pests", "๐Ÿ’ง Irrigation", "๐Ÿ“Š Analytics", "๐Ÿ“ธ Image",
809
+ "๐ŸŽค Voice", "๐Ÿงช Soil", "๐Ÿ“ˆ Yield", "๐Ÿ‘ค Profile"
810
  ])
811
 
812
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
813
+ # TAB 1: AI CHAT
814
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
815
 
816
  with tab1:
817
+ st.markdown("### ๐Ÿ’ฌ Talk to Your AI Copilot")
 
 
 
818
 
819
+ if not st.session_state.openai_client:
820
+ st.warning("โš ๏ธ AI is disabled! Add OPENAI_API_KEY to secrets.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
821
 
822
+ user_input = st.text_input("Your question...", key="chat_input_main")
823
 
824
+ if st.button("๐Ÿš€ Send", key="chat_send_btn"):
825
+ if user_input:
826
+ st.session_state.messages.append(("user", user_input))
827
+
828
+ if st.session_state.openai_client:
829
+ context = {"location": st.session_state.location, "season": get_current_season()}
830
+ with st.spinner("๐Ÿค” Thinking..."):
831
+ ai_response = get_ai_response(
832
+ st.session_state.openai_client,
833
+ user_input,
834
+ context,
835
+ st.session_state.language
836
+ )
837
+ else:
838
+ ai_response = "AI is disabled."
839
+
840
+ st.session_state.messages.append(("ai", ai_response))
841
+ st.rerun()
842
 
843
+ if st.session_state.messages:
844
+ for msg_type, content in st.session_state.messages[-10:]:
845
+ if msg_type == "user":
846
+ st.info(f"๐Ÿ‘จโ€๐ŸŒพ You: {content}")
847
+ else:
848
+ st.success(f"๐Ÿค– Copilot: {content}")
849
+
850
+ if st.button("๐Ÿ—‘๏ธ Clear Chat", key="clear_chat_btn"):
851
+ st.session_state.messages = []
852
+ st.rerun()
853
 
854
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
855
  # TAB 2: WEATHER
856
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
857
 
858
  with tab2:
859
+ st.markdown("### ๐ŸŒค๏ธ Weather & Climate")
860
 
861
+ if st.button("๐Ÿ”„ Refresh Weather", key="weather_refresh"):
862
+ with st.spinner("Fetching..."):
863
  weather = get_weather_data(st.session_state.location)
864
  if weather:
865
+ col1, col2, col3 = st.columns(3)
866
+ col1.metric("๐ŸŒก๏ธ Temperature", f"{weather['temperature']:.1f}ยฐC")
867
+ col2.metric("๐Ÿ’ง Humidity", f"{weather['humidity']}%")
868
+ col3.metric("๐Ÿ’จ Wind", f"{weather['wind_speed']:.1f} m/s")
869
+
870
+ if st.button("๐Ÿ“… Get 7-Day Forecast", key="weather_forecast"):
871
+ forecast_df = get_7day_forecast(st.session_state.location)
872
+ if forecast_df is not None:
873
+ st.dataframe(forecast_df, use_container_width=True)
874
 
875
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
876
  # TAB 3: MARKET PRICES
877
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
878
 
879
  with tab3:
880
+ st.markdown("### ๐Ÿ’ฐ Live Market Prices")
881
 
882
+ if st.button("๐Ÿ”„ Refresh Prices", key="market_refresh"):
883
  live_prices = get_live_market_prices()
884
  if live_prices:
885
+ col1, col2 = st.columns(2)
886
  crops_list = list(live_prices.keys())
887
 
888
+ with col1:
889
+ for crop in crops_list[:4]:
890
+ st.metric(crop, f"โ‚น{live_prices[crop]}")
891
+
892
+ with col2:
893
+ for crop in crops_list[4:]:
894
+ st.metric(crop, f"โ‚น{live_prices[crop]}")
895
 
896
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
897
+ # TAB 4-7: PLACEHOLDER TABS (Crops, Pests, Irrigation, Analytics)
898
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
899
 
900
  with tab4:
901
+ st.markdown("### ๐ŸŒฑ Crop Recommendations")
902
+ st.info("๐ŸŒพ Cotton, Wheat, Rice, Sugarcane - Select based on season")
903
+ st.write("Current Season:", get_current_season())
904
 
905
  with tab5:
906
+ st.markdown("### ๐Ÿ› Pest & Disease Management")
907
+ st.info("Pest management tips and identification guide")
908
 
909
  with tab6:
910
+ st.markdown("### ๐Ÿ’ง Irrigation Management")
911
+ st.info("Smart irrigation scheduling and water conservation")
912
 
913
  with tab7:
914
+ st.markdown("### ๐Ÿ“Š Farm Analytics")
915
+ st.info("Profit calculations and farm statistics")
916
 
917
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
918
+ # TAB 8: IMAGE RECOGNITION (UNIQUE KEYS!)
919
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
920
 
921
  with tab8:
922
+ st.markdown("### ๐Ÿ“ธ Pest & Disease Detection")
923
+ uploaded_file = st.file_uploader("Upload leaf photo", type=['jpg', 'jpeg', 'png'], key="image_uploader")
 
924
 
925
+ if uploaded_file and st.button("๐Ÿ” Analyze", key="image_analyze_btn"):
926
+ if IMAGE_RECOGNITION_AVAILABLE:
927
+ result, error = analyze_plant_disease(uploaded_file)
928
+ if error:
929
+ st.error(error)
930
+ else:
931
+ col1, col2, col3 = st.columns(3)
932
+ col1.metric("Disease", result['disease'].split('-')[0])
933
+ col2.metric("Confidence", f"{result['confidence']:.1f}%")
934
+ col3.metric("Severity", result['severity'])
935
+ else:
936
+ st.warning("Image recognition not available")
 
 
 
 
 
 
 
 
937
 
938
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
939
+ # TAB 9: VOICE (UNIQUE KEYS!)
940
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
941
 
942
  with tab9:
943
+ st.markdown("### ๐ŸŽค Voice Interaction")
944
+ col1, col2 = st.columns(2)
945
+
946
+ with col1:
947
+ if st.button("๐ŸŽ™๏ธ Speak Question", key="voice_input_btn"):
948
+ if VOICE_AVAILABLE:
949
+ text, error = voice_input()
950
+ if error:
951
+ st.error(error)
952
+ elif text:
953
+ st.success(f"You said: {text}")
954
+ else:
955
+ st.warning("Voice not available")
956
+
957
+ with col2:
958
+ if st.button("๐Ÿ”Š Play Response", key="voice_output_btn"):
959
+ if VOICE_AVAILABLE and st.session_state.messages:
960
+ last_response = st.session_state.messages[-1][1]
961
+ voice_output(last_response)
962
+ else:
963
+ st.warning("No response to play")
964
 
965
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
966
+ # TAB 10: SOIL HEALTH (UNIQUE KEYS!)
967
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
968
 
969
  with tab10:
970
+ st.markdown("### ๐Ÿงช Soil Health Monitoring")
971
 
972
  col1, col2, col3 = st.columns(3)
973
  with col1:
974
+ pH = st.slider("Soil pH", 4.0, 9.0, 6.5, key="soil_pH_slider")
975
+ nitrogen = st.slider("Nitrogen (mg/kg)", 0, 1000, 250, key="soil_nitrogen_slider")
976
  with col2:
977
+ phosphorus = st.slider("Phosphorus (mg/kg)", 0, 100, 20, key="soil_phosphorus_slider")
978
+ potassium = st.slider("Potassium (mg/kg)", 0, 500, 150, key="soil_potassium_slider")
979
  with col3:
980
+ organic_matter = st.slider("Organic Matter (%)", 0.0, 10.0, 2.5, key="soil_organic_slider")
981
+ moisture = st.slider("Soil Moisture (%)", 0.0, 50.0, 25.0, key="soil_moisture_slider")
982
 
983
+ if st.button("๐Ÿ’พ Save Soil Test", key="soil_save_btn"):
984
  save_soil_test(st.session_state.location, pH, nitrogen, phosphorus, potassium, organic_matter, moisture)
985
+ st.success("Saved!")
986
 
987
  recommendations = get_soil_recommendations(pH, nitrogen, phosphorus, potassium)
 
988
  for rec in recommendations:
989
  st.markdown(rec)
990
 
991
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
992
+ # TAB 11: YIELD PREDICTION (UNIQUE KEYS!)
993
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
994
 
995
  with tab11:
996
+ st.markdown("### ๐Ÿ“ˆ Yield Prediction")
997
 
998
  col1, col2, col3 = st.columns(3)
999
  with col1:
1000
+ temp = st.slider("Temperature (ยฐC)", 0, 45, 25, key="yield_temp_slider")
1001
+ humidity = st.slider("Humidity (%)", 0, 100, 70, key="yield_humidity_slider")
1002
  with col2:
1003
+ rainfall = st.slider("Rainfall (mm)", 0, 500, 250, key="yield_rainfall_slider")
1004
+ pH = st.slider("Soil pH", 4.0, 9.0, 6.8, key="yield_pH_slider")
1005
  with col3:
1006
+ org_matter = st.slider("Organic Matter (%)", 0.0, 10.0, 2.5, key="yield_orgmatter_slider")
1007
 
1008
+ if st.button("๐Ÿ”ฎ Predict Yield", key="yield_predict_btn"):
1009
  yield_pred = predict_yield(temp, humidity, rainfall, pH, org_matter)
1010
+ st.metric("Predicted Yield", f"{yield_pred:.1f} q/hectare")
 
 
 
 
 
 
 
1011
 
1012
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1013
+ # TAB 12: USER PROFILE (UNIQUE KEYS!)
1014
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1015
 
1016
  with tab12:
1017
+ st.markdown("### ๐Ÿ‘ค User Profile & Settings")
1018
 
1019
  if not st.session_state.user_authenticated:
1020
+ auth_choice = st.radio("Choose", ["๐Ÿ” Login", "๐Ÿ“ Register"], key="auth_choice_radio")
1021
 
1022
+ if auth_choice == "๐Ÿ” Login":
1023
+ username = st.text_input("Username", key="login_username")
1024
+ password = st.text_input("Password", type="password", key="login_password")
 
 
1025
 
1026
+ if st.button("Login", key="login_btn"):
1027
  success, result = login_user(username, password)
 
1028
  if success:
1029
  st.session_state.user_authenticated = True
1030
  st.session_state.username = username
1031
+ st.success("Logged in!")
1032
  st.rerun()
1033
  else:
1034
+ st.error("Invalid credentials")
 
1035
  else:
1036
+ new_username = st.text_input("Username", key="register_username")
1037
+ new_email = st.text_input("Email", key="register_email")
1038
+ new_password = st.text_input("Password", type="password", key="register_password")
 
 
1039
 
1040
+ if st.button("Register", key="register_btn"):
1041
  success, msg = register_user(new_username, new_password, new_email, st.session_state.location)
1042
+ st.success(msg) if success else st.error(msg)
 
 
 
 
 
1043
  else:
1044
+ st.success(f"Logged in as: {st.session_state.username}")
1045
+ if st.button("Logout", key="logout_btn"):
 
1046
  st.session_state.user_authenticated = False
 
1047
  st.rerun()
1048
 
1049
  st.divider()
1050
+ st.markdown("<div style='text-align: center'><p>๐ŸŒพ FARMER COPILOT v3.0 - All 15 Features | Powered by OpenAI</p></div>", unsafe_allow_html=True)