From 56bb0c628184879c4756abfacc21bd4ef8059ace Mon Sep 17 00:00:00 2001 From: Mohammad Sajad Pourajam Date: Fri, 20 Feb 2026 23:15:29 +0330 Subject: [PATCH] Enhance PlantSimulator with yield and yield rate tracking - Added yield and yield rate properties to the PlantState interface. - Implemented computeYieldRate function to calculate yield based on environmental factors and plant growth. - Updated GrowthChart component to visualize yield and yield rate alongside height and leaf count. - Modified PlantSimulator state management to include yield and yield rate history. - Enhanced UI to display current yield and yield rate in the simulator. --- .../farm/plantSimulator/PlantSimulator.tsx | 114 ++++++++++++++++-- 1 file changed, 103 insertions(+), 11 deletions(-) diff --git a/src/views/dashboards/farm/plantSimulator/PlantSimulator.tsx b/src/views/dashboards/farm/plantSimulator/PlantSimulator.tsx index 34c3635..ddae29e 100644 --- a/src/views/dashboards/farm/plantSimulator/PlantSimulator.tsx +++ b/src/views/dashboards/farm/plantSimulator/PlantSimulator.tsx @@ -31,6 +31,8 @@ interface PlantState { height: number // current stem height px (0 → MAX_HEIGHT) leaves: Leaf[] tick: number + yield: number // accumulated yield in grams (0 → MAX_YIELD) + yieldRate: number // current yield production rate g/s } interface EnvironmentSettings { @@ -41,6 +43,7 @@ interface EnvironmentSettings { // ─── Constants ─────────────────────────────────────────────────────────────── const MAX_HEIGHT = 260 +const MAX_YIELD = 500 // max yield in grams const SVG_WIDTH = 200 const SVG_HEIGHT = 320 const STEM_X = SVG_WIDTH / 2 @@ -56,6 +59,16 @@ function growthRate(env: EnvironmentSettings, speed: number): number { return speed * lightFactor * waterFactor } +// Yield rate in g/s: leaves and height progress amplify yield production +function computeYieldRate(env: EnvironmentSettings, leafCount: number, heightProgress: number): number { + const lightFactor = 0.2 + (env.light / 100) * 0.8 + const waterFactor = 0.2 + (env.water / 100) * 0.8 + const leafFactor = leafCount / MAX_LEAVES + // yield only starts after 20% growth and accelerates with more leaves + const maturityFactor = Math.max(0, (heightProgress - 0.2) / 0.8) + return parseFloat((MAX_YIELD * 0.012 * lightFactor * waterFactor * leafFactor * maturityFactor).toFixed(3)) +} + // ─── Plant SVG Component ────────────────────────────────────────────────────── function PlantSVG({ plant, tick }: { plant: PlantState; tick: number }) { @@ -125,10 +138,14 @@ function PlantSVG({ plant, tick }: { plant: PlantState; tick: number }) { function GrowthChart({ heightHistory, - leafHistory + leafHistory, + yieldHistory, + yieldRateHistory }: { heightHistory: number[] leafHistory: number[] + yieldHistory: number[] + yieldRateHistory: number[] }) { const labels = heightHistory.map((_, i) => `${i}s`) @@ -139,7 +156,7 @@ function GrowthChart({ label: 'ارتفاع (px)', data: heightHistory, borderColor: '#4a7c59', - backgroundColor: 'rgba(74,124,89,0.15)', + backgroundColor: 'rgba(74,124,89,0.10)', fill: true, tension: 0.4, pointRadius: 0, @@ -149,11 +166,32 @@ function GrowthChart({ label: 'تعداد برگ', data: leafHistory, borderColor: '#f9c74f', - backgroundColor: 'rgba(249,199,79,0.15)', + backgroundColor: 'rgba(249,199,79,0.10)', fill: true, tension: 0.4, pointRadius: 0, yAxisID: 'yLeaf' + }, + { + label: 'محصول (g)', + data: yieldHistory, + borderColor: '#f97316', + backgroundColor: 'rgba(249,115,22,0.10)', + fill: true, + tension: 0.4, + pointRadius: 0, + yAxisID: 'yYield' + }, + { + label: 'سرعت محصول (g/s)', + data: yieldRateHistory, + borderColor: '#a78bfa', + backgroundColor: 'rgba(167,139,250,0.10)', + fill: true, + tension: 0.4, + pointRadius: 0, + borderDash: [4, 3], + yAxisID: 'yYieldRate' } ] } @@ -162,7 +200,7 @@ function GrowthChart({ responsive: true, animation: { duration: 0 }, plugins: { - legend: { labels: { color: '#e2e8f0', font: { size: 12 } } }, + legend: { labels: { color: '#e2e8f0', font: { size: 11 } } }, title: { display: true, text: 'نمودار رشد گیاه', @@ -192,6 +230,21 @@ function GrowthChart({ ticks: { color: '#f9c74f' }, grid: { display: false }, title: { display: true, text: 'برگ', color: '#f9c74f' } + }, + yYield: { + type: 'linear' as const, + position: 'left' as const, + min: 0, + max: MAX_YIELD, + display: false, + grid: { display: false } + }, + yYieldRate: { + type: 'linear' as const, + position: 'right' as const, + min: 0, + display: false, + grid: { display: false } } } } @@ -206,18 +259,22 @@ export default function PlantSimulator() { const [speed, setSpeed] = useState(1.5) // px per tick base const [env, setEnv] = useState({ light: 75, water: 65 }) - const [plant, setPlant] = useState({ height: 0, leaves: [], tick: 0 }) + const [plant, setPlant] = useState({ height: 0, leaves: [], tick: 0, yield: 0, yieldRate: 0 }) const [heightHistory, setHeightHistory] = useState([0]) const [leafHistory, setLeafHistory] = useState([0]) + const [yieldHistory, setYieldHistory] = useState([0]) + const [yieldRateHistory, setYieldRateHistory] = useState([0]) const intervalRef = useRef | null>(null) const tickRef = useRef(0) const historyIntervalRef = useRef | null>(null) const reset = useCallback(() => { - setPlant({ height: 0, leaves: [], tick: 0 }) + setPlant({ height: 0, leaves: [], tick: 0, yield: 0, yieldRate: 0 }) setHeightHistory([0]) setLeafHistory([0]) + setYieldHistory([0]) + setYieldRateHistory([0]) tickRef.current = 0 }, []) @@ -258,7 +315,12 @@ export default function PlantSimulator() { scale: Math.min(l.scale + 0.025, 1) })) - return { height: newHeight, leaves: grownLeaves, tick: t } + const heightProgress = newHeight / MAX_HEIGHT + const currentYieldRate = computeYieldRate(env, grownLeaves.length, heightProgress) + // accumulate yield each tick (33ms ≈ 0.033s) + const newYield = Math.min(prev.yield + currentYieldRate * 0.033, MAX_YIELD) + + return { height: newHeight, leaves: grownLeaves, tick: t, yield: newYield, yieldRate: currentYieldRate } }) }, 33) @@ -278,6 +340,8 @@ export default function PlantSimulator() { setPlant(prev => { setHeightHistory(h => [...h.slice(-59), Math.round(prev.height)]) setLeafHistory(l => [...l.slice(-59), prev.leaves.length]) + setYieldHistory(y => [...y.slice(-59), parseFloat(prev.yield.toFixed(1))]) + setYieldRateHistory(r => [...r.slice(-59), prev.yieldRate]) return prev }) }, 1000) @@ -312,6 +376,14 @@ export default function PlantSimulator() {
{plant.leaves.length}
تعداد برگ
+
+
{plant.yield.toFixed(1)}
+
محصول (g)
+
+
+
{plant.yieldRate.toFixed(3)}
+
سرعت محصول (g/s)
+
{isFinished && ( @@ -400,10 +472,15 @@ export default function PlantSimulator() { {/* ── Right: Chart ── */}
- + {/* Info cards */} -
+
پیشرفت رشد
@@ -438,6 +515,20 @@ export default function PlantSimulator() {
{env.water}%
+ +
+
محصول دهی
+
+
+
+
+ {plant.yield.toFixed(1)}g + {plant.yieldRate.toFixed(3)} g/s +
+
{/* Description */} @@ -445,8 +536,9 @@ export default function PlantSimulator() {

این شبیه‌ساز رشد گیاه را بر اساس سرعت پایه، میزان نور خورشید و آب دریافتی محاسبه می‌کند. هر برگ به صورت تدریجی روی ساقه ظاهر شده و با حرکت طبیعی - در باد نمایش داده می‌شود. نمودار تغییرات ارتفاع و تعداد برگ‌ها را در طول - زمان ثبت می‌کند. + در باد نمایش داده می‌شود. محصول‌دهی (g) پس از ۲۰٪ رشد شروع شده + و با تعداد برگ، نور و آب شتاب می‌گیرد. سرعت محصول (g/s) نشان‌دهنده + نرخ لحظه‌ای تولید است. نمودار تغییرات همه شاخص‌ها را در طول زمان ثبت می‌کند.