Mudah Tani

Savings Methodology

v1.0 · May 2026 · Source data: market-prices.json v1.1.0

Versi Bahasa Indonesia akan datang. Silakan rujuk versi Bahasa Inggris di bawah untuk saat ini.

How Mudah Tani calculates the "you saved RM X" figure on your home dashboard.

How savings are calculated

When you log a harvest in the app — for example "5 cucumbers" or "1.2 kg of kangkung" — we estimate what those same vegetables would have cost at a market or supermarket. That estimated cost is your savings.

The formula is:

savings = harvest_in_kg × price_per_kg

For weight-based logs (kg, g), the harvest is already in kg. For piece-based logs (fruits, leaves, bunches, etc.), we multiply your quantity by a per-unit weight for that crop, then by the price per kg.

Worked example

You logged 5 tomatoes from your garden. The app's data says:

The math is:

5 fruits × 80 g/fruit = 400 g = 0.4 kg
0.4 kg × MYR 6/kg = MYR 2.40 saved

If you logged the price you actually paid for tomatoes recently (the "price at harvest" field when adding a yield), we use thatinstead of the market estimate — see "Priority ladder" below.

Before your first harvest — the estimate

Until you've logged a real harvest, there's nothing to calculate realized savings from — so instead the app shows an estimate("Estimated RM X when you harvest") so you can see the potential payoff of what you're already growing. Once you log your first harvest, the realized figure above takes over and the estimate disappears (so the two never double-count).

The estimate is driven by your Growing space setting — the small card at the bottom of My Garden (you can also tap the estimate itself to adjust it). For each active plant we project an expected harvest from its growing area and multiply by the same market price used everywhere else:

estimated savings = Σ (expected yield for the plant's area × price per kg)
expected yield = crop's expected kg per 100 m² × the plant's growing area

How your growing area is counted depends on the space type you picked:

Worked example

Say you have 5 pots of leafy greens (each pot ≈ 0.1 m²), the container default:

5 pots × 0.1 m²/pot = 0.5 m²
0.5 m² × ~150 kg/100 m² expected = 0.75 kg
0.75 kg × MYR 4/kg = MYR 3.00 estimated

A few honesty notes about the estimate:

Priority ladder — which price we use

For every harvest we calculate savings against, the app picks the price in this order:

  1. Your own "price at harvest" entry — if you typed in what tomatoes cost at the market that week, this wins. Most accurate, most personal.
  2. Typical market price from market-prices.json — our central estimate for that crop.
  3. Legacy single-point market price— same data, kept around for older app installs that haven't refreshed yet.

If none of the above produces a positive number, that harvest doesn't contribute to your savings figure (we won't make up a number).

Where the prices come from

Prices live in src/features/playbooks/data/market-prices.json — a versioned JSON file shipped with the app and seeded into your device's local database on first launch.

For Malaysia (MYR):

DOA wholesale price feeds were considered for high-volatility crops (chili, tomato, leafy greens) but the actual market-prices.json v1.1.0 data set is built from the three sources above. DOA integration is tracked as a separate post-MVP backlog item.

For Indonesia (IDR):

Initial extrapolation from MYR prices using the typical 2,000–2,500× ratio observed across the same crops at Pasar Tradisional Jakarta. This is a transparent limitation: the IDR figures are not first-party sampled yet. They are a working starting point; first-party Indonesia sampling is a tracked post-launch task.

Sourcing was performed in May 2026. Each row in market-prices.json carries its own as_of date so individual rows can be refreshed for volatile crops (chili spikes mid-season) without touching the rest.

Why prices have a range

Real produce prices vary by:

To be honest about that variation, every crop in market-prices.json carries three price points per currency:

The savings figure uses typical by default. The range is shown alongside on the Savings Detail screen so you can sanity-check the math.

For the initial v1.1.0 data, the low/high range is ±20% from the typical value — a conservative placeholder pending real per-crop sampling. Some crops have known wider volatility (chili, watermelon) and will get tighter ranges in future updates.

What the defaults assume

For piece-based units (fruits, leaves, bunches, etc.), the app needs a kg-per-unit conversion factor. Those defaults live in crops.json per crop and are deliberately conservative — leaning slightly low. Underclaiming is reputationally safer than overclaiming.

Notable defaults:

If your harvest doesn't match the default — beefsteak tomatoes are 3–4× heavier than 80 g — the app lets you override the per-unit factor. See "How to correct" below.

A small set of crops are priced per-piecerather than per-kg, because that's how they're commonly sold:

For those, the savings math applies the price directly to the piece count rather than going through a kg conversion.

Limitations

We try to be upfront about what this number doesn't tell you:

These limitations don't break the savings claim; they bound how precise it can be. If you want a more accurate figure, log the price at harvest when adding a yield — that bypasses every estimate and uses your real number.

How users can correct

If the default doesn't match your reality, you have two override paths inside the app:

1. Edit a per-crop factor (Savings Detail screen)

On the Savings Detail screen, every per-crop row that uses a piece-based unit shows a pencil icon. Tap it to enter your own kg-per-unit factor.

Example: you grow beefsteak tomatoes that average 250 g, not 80 g. Tap the pencil on the tomato row, enter 250, and the savings figure recalculates instantly — and persists for all your future tomato harvests.

2. Log a harvest with your actual price (Add Yield screen)

When you add a yield, the price at harvest field lets you record what you actually paid for the same crop that week. That value wins over every default estimate.

Both paths feed back into the priority ladder. If you don't override anything, the app uses the conservative defaults documented above.

Questions or corrections?

Email support@mudahtani.my with the crop name, your local price, and the source (which market, when). We re-sample volatile crops based on user reports.


Last updated: 2026-05-31 · Methodology version: 1.1 (added pre-harvest growing-space estimate) · Source data: market-prices.json v1.1.0