Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- app.py +103 -0
- templates/index.html +351 -0
app.py
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import Flask, render_template, request
|
2 |
+
from markupsafe import Markup
|
3 |
+
from google import genai
|
4 |
+
|
5 |
+
app = Flask(__name__)
|
6 |
+
|
7 |
+
# Initialize the Gemini API client using your API key
|
8 |
+
client = genai.Client(api_key="AIzaSyBtXV2xJbrWVV57B5RWy_meKXOA59HFMeY")
|
9 |
+
|
10 |
+
|
11 |
+
@app.route('/', methods=['GET', 'POST'])
|
12 |
+
def index():
|
13 |
+
if request.method == 'POST':
|
14 |
+
# Retrieve farm details
|
15 |
+
location = request.form.get('location')
|
16 |
+
season = request.form.get('season')
|
17 |
+
total_area = request.form.get('total_area')
|
18 |
+
language = request.form.get('language', 'English') # Get selected language with English as default
|
19 |
+
|
20 |
+
# Retrieve crop details
|
21 |
+
crop_names = request.form.getlist('crop_name')
|
22 |
+
crop_areas = request.form.getlist('crop_area')
|
23 |
+
crops = []
|
24 |
+
for name, area in zip(crop_names, crop_areas):
|
25 |
+
if name.strip() and area.strip():
|
26 |
+
crops.append({'name': name.strip(), 'area': area.strip()})
|
27 |
+
|
28 |
+
# Construct a descriptive summary of the crop details
|
29 |
+
crop_details = ", ".join([f"{crop['name']} ({crop['area']} acres)" for crop in crops])
|
30 |
+
|
31 |
+
# Build the prompt that instructs the API to generate a fully formatted HTML page with enhanced CSS styling.
|
32 |
+
prompt = f"""
|
33 |
+
You are a skilled agriculture expert. I am providing you with the following farm details and crop information:
|
34 |
+
|
35 |
+
- Location: {location}
|
36 |
+
- Season: {season}
|
37 |
+
- Total Farm Area: {total_area} acres
|
38 |
+
- Crop Details: {crop_details}
|
39 |
+
|
40 |
+
Using the above input, please generate a fully formatted HTML page with enhanced CSS styling that includes the following sections:
|
41 |
+
i dont want any spacing remove extra spaicng if any
|
42 |
+
|
43 |
+
1. **Main Heading:**
|
44 |
+
- A centrally aligned, bold heading in green titled "Crop Swapping Strategies" with no extra spacing before the heading or after the report. Use medium overall spacing, clear font sizes for both headings and points, and ensure the report is easily understandable by farmers. Tables should be designed for optimal readability.
|
45 |
+
|
46 |
+
2. **Current Strategy Statistics:**
|
47 |
+
- A left-aligned, blue bold subheading "Current Strategy Statistics".
|
48 |
+
- Below it, include a green table with columns for:
|
49 |
+
- Crop Name
|
50 |
+
- Gross Revenue
|
51 |
+
- Yearly Production
|
52 |
+
- Yearly Expenses
|
53 |
+
- Overall Profit Percentage
|
54 |
+
- Populate the table with realistic hypothetical data based on the provided crop details.
|
55 |
+
|
56 |
+
3. **Year Crops Swapping Strategies (3-Year Forecast):**
|
57 |
+
- A left-aligned, blue bold subheading titled "#Year Crops Swapping Strategies".
|
58 |
+
- Create a green table that displays season-wise cropping strategies over the next three years, ensuring clarity with concise headers and data. Incorporate land optimization details (e.g., tomato: 1.5 acres) and consider different cropping seasons such as Rabi and Kharif.
|
59 |
+
|
60 |
+
4. **Swapping Strategy Statistics:**
|
61 |
+
- A left-aligned, blue bold subheading "Swapping Strategy Statistics".
|
62 |
+
- Add a green table showing new strategy data including:
|
63 |
+
- Production
|
64 |
+
- Gross Income
|
65 |
+
- Profit Percentage
|
66 |
+
- Use realistic figures that align with crop swapping strategies.
|
67 |
+
|
68 |
+
5. **Comparative Analysis:**
|
69 |
+
- Include a section with a blue left-aligned subheading "Comparison of Current and Swapped Strategy Statistics".
|
70 |
+
- Present a comparative table clearly outlining differences between the current strategy and the new swapped strategy.
|
71 |
+
|
72 |
+
6. **Insights and Recommendations:**
|
73 |
+
- At the bottom of the page, include a bullet-point list with short, concise sentences offering insights, recommendations, and questions.
|
74 |
+
- Style each bullet point in bold with yellow highlights on key statistics and numbers.
|
75 |
+
- Optimize spacing and margins to ensure a visually clear layout.
|
76 |
+
|
77 |
+
Additionally, design interactive, beautiful, and colorful tables. Increase the font size for headings and reduce excessive spacing to produce a rich, detailed, and farmer-friendly report using realistic data. Do not include any explanations of the changes.
|
78 |
+
|
79 |
+
IMPORTANT: Give the entire response in {language} language. All text, headings, and content should be in {language}.
|
80 |
+
|
81 |
+
IMPORTANT: Do not add any extra spacing at the beginning or end of the response. Remove any extra spacing.
|
82 |
+
"""
|
83 |
+
|
84 |
+
# Call the Gemini API with the constructed prompt
|
85 |
+
response = client.models.generate_content(
|
86 |
+
model="gemini-2.0-flash",
|
87 |
+
contents=prompt
|
88 |
+
)
|
89 |
+
|
90 |
+
# Extract the generated text (HTML)
|
91 |
+
result_html = response.text
|
92 |
+
|
93 |
+
# Remove any extra spacing at the beginning and end of the response
|
94 |
+
result_html = result_html.strip()
|
95 |
+
|
96 |
+
# Pass the HTML to the template as 'safe' so it's rendered properly
|
97 |
+
return render_template('index.html', result=Markup(result_html))
|
98 |
+
|
99 |
+
return render_template('index.html')
|
100 |
+
|
101 |
+
|
102 |
+
if __name__ == '__main__':
|
103 |
+
app.run(debug=True)
|
templates/index.html
ADDED
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8" />
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6 |
+
<title>Crop Swapping Strategy Optimizer</title>
|
7 |
+
<!-- Tailwind CSS CDN -->
|
8 |
+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet" />
|
9 |
+
<!-- Add Font Awesome for better icons -->
|
10 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" />
|
11 |
+
<!-- Add Animation library -->
|
12 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
|
13 |
+
<!-- Custom CSS for Enhanced UI -->
|
14 |
+
<style>
|
15 |
+
/* Custom gradient background with animation */
|
16 |
+
body {
|
17 |
+
background: linear-gradient(120deg, #e0f2f1, #f0fff4, #e8f5e9);
|
18 |
+
background-size: 400% 400%;
|
19 |
+
animation: gradientBG 15s ease infinite;
|
20 |
+
}
|
21 |
+
|
22 |
+
@keyframes gradientBG {
|
23 |
+
0% { background-position: 0% 50%; }
|
24 |
+
50% { background-position: 100% 50%; }
|
25 |
+
100% { background-position: 0% 50%; }
|
26 |
+
}
|
27 |
+
|
28 |
+
/* Card hover effects */
|
29 |
+
.card-hover {
|
30 |
+
transition: all 0.3s ease;
|
31 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
32 |
+
}
|
33 |
+
|
34 |
+
.card-hover:hover {
|
35 |
+
transform: translateY(-5px);
|
36 |
+
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
|
37 |
+
}
|
38 |
+
|
39 |
+
/* Button animations */
|
40 |
+
.btn-animated {
|
41 |
+
position: relative;
|
42 |
+
overflow: hidden;
|
43 |
+
transition: all 0.3s ease;
|
44 |
+
}
|
45 |
+
|
46 |
+
.btn-animated:after {
|
47 |
+
content: '';
|
48 |
+
position: absolute;
|
49 |
+
top: 50%;
|
50 |
+
left: 50%;
|
51 |
+
width: 5px;
|
52 |
+
height: 5px;
|
53 |
+
background: rgba(255, 255, 255, 0.5);
|
54 |
+
opacity: 0;
|
55 |
+
border-radius: 100%;
|
56 |
+
transform: scale(1, 1) translate(-50%);
|
57 |
+
transform-origin: 50% 50%;
|
58 |
+
}
|
59 |
+
|
60 |
+
.btn-animated:hover:after {
|
61 |
+
animation: ripple 1s ease-out;
|
62 |
+
}
|
63 |
+
|
64 |
+
@keyframes ripple {
|
65 |
+
0% {
|
66 |
+
transform: scale(0, 0);
|
67 |
+
opacity: 0.5;
|
68 |
+
}
|
69 |
+
100% {
|
70 |
+
transform: scale(20, 20);
|
71 |
+
opacity: 0;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
/* Input focus animations */
|
76 |
+
.input-focus {
|
77 |
+
transition: all 0.3s ease;
|
78 |
+
border-left: 2px solid transparent;
|
79 |
+
}
|
80 |
+
|
81 |
+
.input-focus:focus {
|
82 |
+
border-left: 2px solid #4CAF50;
|
83 |
+
transform: translateX(3px);
|
84 |
+
}
|
85 |
+
|
86 |
+
/* Table row animations */
|
87 |
+
.table-row {
|
88 |
+
transition: all 0.2s ease;
|
89 |
+
}
|
90 |
+
|
91 |
+
.table-row:hover {
|
92 |
+
background-color: #f0fff4;
|
93 |
+
}
|
94 |
+
|
95 |
+
/* Styling for the generated plain text output */
|
96 |
+
.plain-output {
|
97 |
+
font-size: 1rem;
|
98 |
+
line-height: 1.8;
|
99 |
+
white-space: pre-wrap; /* Preserves new lines */
|
100 |
+
padding: 1.5em;
|
101 |
+
background: #ffffff;
|
102 |
+
border-left: 4px solid #4CAF50;
|
103 |
+
border-radius: 4px;
|
104 |
+
color: #333;
|
105 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
106 |
+
transition: all 0.3s ease;
|
107 |
+
}
|
108 |
+
|
109 |
+
.plain-output:hover {
|
110 |
+
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.1);
|
111 |
+
}
|
112 |
+
|
113 |
+
/* Custom scrollbar */
|
114 |
+
::-webkit-scrollbar {
|
115 |
+
width: 8px;
|
116 |
+
height: 8px;
|
117 |
+
}
|
118 |
+
|
119 |
+
::-webkit-scrollbar-track {
|
120 |
+
background: #f1f1f1;
|
121 |
+
border-radius: 10px;
|
122 |
+
}
|
123 |
+
|
124 |
+
::-webkit-scrollbar-thumb {
|
125 |
+
background: #4CAF50;
|
126 |
+
border-radius: 10px;
|
127 |
+
}
|
128 |
+
|
129 |
+
::-webkit-scrollbar-thumb:hover {
|
130 |
+
background: #388E3C;
|
131 |
+
}
|
132 |
+
|
133 |
+
/* Add crop button animation */
|
134 |
+
.add-row-btn {
|
135 |
+
transition: all 0.3s ease;
|
136 |
+
}
|
137 |
+
|
138 |
+
.add-row-btn:hover {
|
139 |
+
transform: translateY(-2px);
|
140 |
+
}
|
141 |
+
|
142 |
+
/* Remove button styling */
|
143 |
+
.remove-btn {
|
144 |
+
transition: all 0.2s ease;
|
145 |
+
opacity: 0.7;
|
146 |
+
}
|
147 |
+
|
148 |
+
.remove-btn:hover {
|
149 |
+
opacity: 1;
|
150 |
+
transform: scale(1.1);
|
151 |
+
}
|
152 |
+
|
153 |
+
/* Page title animation */
|
154 |
+
.title-animate {
|
155 |
+
animation: fadeInDown 1s ease-out;
|
156 |
+
}
|
157 |
+
|
158 |
+
@keyframes fadeInDown {
|
159 |
+
from {
|
160 |
+
opacity: 0;
|
161 |
+
transform: translate3d(0, -20px, 0);
|
162 |
+
}
|
163 |
+
to {
|
164 |
+
opacity: 1;
|
165 |
+
transform: translate3d(0, 0, 0);
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
/* Language selector animation */
|
170 |
+
.language-selector {
|
171 |
+
transition: all 0.3s ease;
|
172 |
+
border-bottom: 2px solid transparent;
|
173 |
+
}
|
174 |
+
|
175 |
+
.language-selector:hover {
|
176 |
+
border-bottom: 2px solid #4CAF50;
|
177 |
+
}
|
178 |
+
</style>
|
179 |
+
</head>
|
180 |
+
<body class="min-h-screen flex flex-col items-center justify-center p-6">
|
181 |
+
<div class="w-full max-w-4xl animate__animated animate__fadeIn">
|
182 |
+
<h1 class="text-4xl font-bold text-center text-green-700 mb-8 title-animate">
|
183 |
+
<i class="fas fa-seedling mr-2"></i>Crop Swapping Strategy Optimizer
|
184 |
+
</h1>
|
185 |
+
|
186 |
+
<form action="/" method="POST" class="bg-white shadow-lg rounded-lg px-8 pt-6 pb-8 mb-6 card-hover">
|
187 |
+
<!-- Farm Information -->
|
188 |
+
<div class="grid md:grid-cols-4 gap-4 mb-6">
|
189 |
+
<div>
|
190 |
+
<label class="block text-green-700 text-sm font-bold mb-2" for="location">
|
191 |
+
<i class="fas fa-map-marker-alt mr-1"></i> Location
|
192 |
+
</label>
|
193 |
+
<input class="shadow appearance-none border rounded w-full py-3 px-4 text-green-700 leading-tight focus:outline-none focus:shadow-outline input-focus"
|
194 |
+
id="location" name="location" type="text" placeholder="Enter location" required />
|
195 |
+
</div>
|
196 |
+
|
197 |
+
<div>
|
198 |
+
<label class="block text-green-700 text-sm font-bold mb-2" for="season">
|
199 |
+
<i class="fas fa-cloud-sun mr-1"></i> Season
|
200 |
+
</label>
|
201 |
+
<select id="season" name="season" class="shadow appearance-none border rounded w-full py-3 px-4 text-green-700 leading-tight focus:outline-none focus:shadow-outline input-focus" required>
|
202 |
+
<option value="" disabled selected>Select Season</option>
|
203 |
+
<option value="Rabi">Rabi</option>
|
204 |
+
<option value="Kharif">Kharif</option>
|
205 |
+
<option value="Zaid">Zaid</option>
|
206 |
+
</select>
|
207 |
+
</div>
|
208 |
+
|
209 |
+
<div>
|
210 |
+
<label class="block text-green-700 text-sm font-bold mb-2" for="total_area">
|
211 |
+
<i class="fas fa-ruler-combined mr-1"></i> Total Farm Area (acres)
|
212 |
+
</label>
|
213 |
+
<input class="shadow appearance-none border rounded w-full py-3 px-4 text-green-700 leading-tight focus:outline-none focus:shadow-outline input-focus"
|
214 |
+
id="total_area" name="total_area" type="number" step="0.1" placeholder="Enter total farm area" required />
|
215 |
+
</div>
|
216 |
+
|
217 |
+
<div>
|
218 |
+
<label class="block text-green-700 text-sm font-bold mb-2" for="language">
|
219 |
+
<i class="fas fa-language mr-1"></i> Language
|
220 |
+
</label>
|
221 |
+
<select id="language" name="language" class="shadow appearance-none border rounded w-full py-3 px-4 text-green-700 leading-tight focus:outline-none focus:shadow-outline input-focus language-selector">
|
222 |
+
<option value="English">English</option>
|
223 |
+
<option value="Marathi">Marathi</option>
|
224 |
+
<option value="Hindi">Hindi</option>
|
225 |
+
<option value="Urdu">Urdu</option>
|
226 |
+
<option value="Bengali">Bengali</option>
|
227 |
+
<option value="Odia">Odia</option>
|
228 |
+
<option value="Telugu">Telugu</option>
|
229 |
+
<option value="Tamil">Tamil</option>
|
230 |
+
</select>
|
231 |
+
</div>
|
232 |
+
</div>
|
233 |
+
|
234 |
+
<!-- Dynamic Crop Details Table -->
|
235 |
+
<h2 class="text-2xl font-semibold text-green-600 mt-8 mb-4 text-center animate__animated animate__fadeIn">
|
236 |
+
<i class="fas fa-leaf mr-2"></i>Crop Details
|
237 |
+
</h2>
|
238 |
+
|
239 |
+
<div class="overflow-x-auto mb-6 rounded-lg shadow">
|
240 |
+
<table class="min-w-full divide-y divide-green-200" id="cropTable">
|
241 |
+
<thead class="bg-green-100">
|
242 |
+
<tr>
|
243 |
+
<th class="px-6 py-3 text-left text-xs font-medium text-green-700 uppercase tracking-wider">Crop Name</th>
|
244 |
+
<th class="px-6 py-3 text-left text-xs font-medium text-green-700 uppercase tracking-wider">Area (acres)</th>
|
245 |
+
<th class="px-6 py-3"></th>
|
246 |
+
</tr>
|
247 |
+
</thead>
|
248 |
+
<tbody class="bg-white divide-y divide-green-200">
|
249 |
+
<!-- Initial Crop Row -->
|
250 |
+
<tr class="table-row animate__animated animate__fadeIn">
|
251 |
+
<td class="px-6 py-4 whitespace-nowrap">
|
252 |
+
<input name="crop_name" type="text" placeholder="e.g., Tomato"
|
253 |
+
class="shadow appearance-none border rounded w-full py-2 px-3 text-green-700 input-focus" />
|
254 |
+
</td>
|
255 |
+
<td class="px-6 py-4 whitespace-nowrap">
|
256 |
+
<input name="crop_area" type="number" step="0.1" placeholder="e.g., 2 or 1.5"
|
257 |
+
class="shadow appearance-none border rounded w-full py-2 px-3 text-green-700 input-focus" />
|
258 |
+
</td>
|
259 |
+
<td class="px-6 py-4 whitespace-nowrap">
|
260 |
+
<button type="button" class="text-red-500 hover:text-red-700 remove-btn" onclick="removeRow(this)">
|
261 |
+
<i class="fas fa-trash-alt"></i>
|
262 |
+
</button>
|
263 |
+
</td>
|
264 |
+
</tr>
|
265 |
+
</tbody>
|
266 |
+
</table>
|
267 |
+
</div>
|
268 |
+
|
269 |
+
<div class="mb-6 flex justify-center">
|
270 |
+
<button type="button" onclick="addRow()"
|
271 |
+
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded add-row-btn btn-animated">
|
272 |
+
<i class="fas fa-plus mr-2"></i>Add Crop
|
273 |
+
</button>
|
274 |
+
</div>
|
275 |
+
|
276 |
+
<div class="flex items-center justify-center">
|
277 |
+
<button class="bg-green-500 hover:bg-green-700 text-white font-bold py-3 px-6 rounded-lg focus:outline-none focus:shadow-outline btn-animated" type="submit">
|
278 |
+
<i class="fas fa-magic mr-2"></i>Optimize Strategy
|
279 |
+
</button>
|
280 |
+
</div>
|
281 |
+
</form>
|
282 |
+
|
283 |
+
<!-- Render the optimized output if available -->
|
284 |
+
{% if result %}
|
285 |
+
<div class="bg-white shadow-lg rounded-lg px-8 pt-6 pb-8 animate__animated animate__fadeInUp card-hover">
|
286 |
+
<h2 class="text-2xl font-bold text-center text-green-700 mb-4">
|
287 |
+
<i class="fas fa-chart-line mr-2"></i>Optimized Crop Swapping Strategies
|
288 |
+
</h2>
|
289 |
+
<div class="plain-output">
|
290 |
+
{{ result|safe }}
|
291 |
+
</div>
|
292 |
+
</div>
|
293 |
+
{% endif %}
|
294 |
+
|
295 |
+
<footer class="text-center text-green-700 mt-6 opacity-75 animate__animated animate__fadeIn">
|
296 |
+
<p>© 2025 Crop Swapping Strategy Optimizer</p>
|
297 |
+
</footer>
|
298 |
+
</div>
|
299 |
+
|
300 |
+
<script>
|
301 |
+
// Function to add a new crop row with animation
|
302 |
+
function addRow() {
|
303 |
+
const tableBody = document.querySelector("#cropTable tbody");
|
304 |
+
const newRow = document.createElement("tr");
|
305 |
+
newRow.className = "table-row animate__animated animate__fadeIn";
|
306 |
+
newRow.innerHTML = `
|
307 |
+
<td class="px-6 py-4 whitespace-nowrap">
|
308 |
+
<input name="crop_name" type="text" placeholder="e.g., Crop Name"
|
309 |
+
class="shadow appearance-none border rounded w-full py-2 px-3 text-green-700 input-focus" />
|
310 |
+
</td>
|
311 |
+
<td class="px-6 py-4 whitespace-nowrap">
|
312 |
+
<input name="crop_area" type="number" step="0.1" placeholder="e.g., Area"
|
313 |
+
class="shadow appearance-none border rounded w-full py-2 px-3 text-green-700 input-focus" />
|
314 |
+
</td>
|
315 |
+
<td class="px-6 py-4 whitespace-nowrap">
|
316 |
+
<button type="button" class="text-red-500 hover:text-red-700 remove-btn" onclick="removeRow(this)">
|
317 |
+
<i class="fas fa-trash-alt"></i>
|
318 |
+
</button>
|
319 |
+
</td>
|
320 |
+
`;
|
321 |
+
tableBody.appendChild(newRow);
|
322 |
+
}
|
323 |
+
|
324 |
+
// Function to remove a crop row with animation
|
325 |
+
function removeRow(button) {
|
326 |
+
const row = button.closest("tr");
|
327 |
+
row.classList.add("animate__animated", "animate__fadeOut");
|
328 |
+
|
329 |
+
// Wait for animation to complete before removing the row
|
330 |
+
row.addEventListener("animationend", function() {
|
331 |
+
row.remove();
|
332 |
+
});
|
333 |
+
}
|
334 |
+
|
335 |
+
// Add form submission animation
|
336 |
+
document.querySelector("form").addEventListener("submit", function() {
|
337 |
+
this.classList.add("animate__animated", "animate__pulse");
|
338 |
+
});
|
339 |
+
|
340 |
+
// Animate input fields on focus
|
341 |
+
document.querySelectorAll("input, select").forEach(element => {
|
342 |
+
element.addEventListener("focus", function() {
|
343 |
+
this.classList.add("animate__animated", "animate__pulse");
|
344 |
+
this.addEventListener("animationend", function() {
|
345 |
+
this.classList.remove("animate__animated", "animate__pulse");
|
346 |
+
});
|
347 |
+
});
|
348 |
+
});
|
349 |
+
</script>
|
350 |
+
</body>
|
351 |
+
</html>
|