Skip to content

Commit 030ef26

Browse files
[#713] Fix Advanced Modelling Tool: surplus handling, feasibility signal rounding, and impossible scenario warning
1 parent 4851585 commit 030ef26

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

GEMINI.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ Income Driver Calculator (IDC) is a web application designed to help companies t
158158
- Refined surplus verification logic to compare total calculated income (primary + others) against the benchmark target.
159159
- Decoupled surplus detection from adjusted targets to ensure baseline feasibility checks remain consistent with the original segment benchmark.
160160
- Fixed decimal input issue in `AdvancedModellingTool.js` by replacing standard `Input` with `InputNumber` and integrating `InputNumberThousandFormatter`.
161+
- Refined Advanced Modelling Tool: implemented "current value" clamping for surplus scenarios to avoid confusing negative results.
162+
- Fixed feasibility signal bug by implementing 2-decimal rounding for precision-safe comparisons.
163+
- Replaced Price Breakdown chart with a "physically impossible" warning alert for scenarios with negative required values.
164+
- Refined guidance UI by removing icons from modelling tool alerts for a cleaner appearance.
161165
- **Visualization & Step 3/4 Fixes (Issue #719)**:
162166
- Resolved graph loading issues in "Understand Income Gap" and "Assess Impact Mitigation Strategies" by refining aggregator question identification for primary, secondary, and tertiary commodities.
163167
- Implemented absolute-wedge rendering in the shared `Pie.js` component to visualize surpluses (negative gaps) while maintaining signed labels and tooltips.

frontend/src/pages/cases/components/AdvancedModellingTool.js

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -862,17 +862,16 @@ const AdvancedModellingTool = () => {
862862
state = "surplus";
863863
message =
864864
"Farmers in this segment already earn more than the income target. In this calculated scenario, incomes would decrease.";
865-
} else if (result < 0 && selectedDriver === "cop") {
865+
} else if (result < 0) {
866866
state = "impossible";
867867
message =
868-
"It is not physically possible to reach the income target with the specified model values.";
869-
} else if (result < 0 && selectedDriver !== "cop") {
870-
// This case handles negative price or volume results which are impossible but not a "surplus" in terms of current earnings
871-
state = "impossible";
872-
message = "Impossible target: required value is negative.";
868+
selectedDriver === "cop"
869+
? "It is not physically possible to reach the income target with the specified model values."
870+
: "Impossible target: required value is negative.";
873871
}
874872

875-
const finalResult = Math.max(0, result);
873+
// If surplus, we show the current value of the driver to avoid confusion with theoretical/negative values
874+
const finalResult = state === "surplus" ? drivers[selectedDriver] : result;
876875

877876
// Calculate current scenario values for the breakdown
878877
const currentPrice =
@@ -917,6 +916,7 @@ const AdvancedModellingTool = () => {
917916
isTargetMet: isTargetMet,
918917
state: state,
919918
message: message,
919+
rawResult: result, // Store raw result for visual logic
920920
},
921921
}));
922922
};
@@ -1064,13 +1064,26 @@ const AdvancedModellingTool = () => {
10641064
"feasible",
10651065
selectedDriver
10661066
);
1067+
1068+
// Round to 2 decimals for precision-safe comparison
1069+
const roundedResult =
1070+
Math.round((scenarioResult.value || 0) * 100) / 100;
1071+
const roundedFeasible =
1072+
Math.round((feasibleValue || 0) * 100) / 100;
1073+
10671074
let isFeasible = false;
1068-
if (selectedDriver === "cop") {
1075+
if (scenarioResult.state === "surplus") {
1076+
// If we are in surplus, the current performance is already feasibility-proven
1077+
isFeasible = true;
1078+
} else if (scenarioResult.rawResult < 0) {
1079+
// Physically impossible values are never feasible
1080+
isFeasible = false;
1081+
} else if (selectedDriver === "cop") {
10691082
// For CoP, a higher required value is "easier" (more room for expense)
1070-
isFeasible = scenarioResult.value >= feasibleValue;
1083+
isFeasible = roundedResult >= roundedFeasible;
10711084
} else {
10721085
// For Price/Volume, a lower required value is "easier" (less performance needed)
1073-
isFeasible = scenarioResult.value <= feasibleValue;
1086+
isFeasible = roundedResult <= roundedFeasible;
10741087
}
10751088

10761089
return (
@@ -1329,6 +1342,22 @@ const AdvancedModellingTool = () => {
13291342
(() => {
13301343
const scenarioResult =
13311344
calculationResults[activeScenario];
1345+
1346+
// Physically impossible warning
1347+
if (scenarioResult.rawResult < 0) {
1348+
const driverLabel =
1349+
driverLabels[selectedDriver] || selectedDriver;
1350+
return (
1351+
<div className="impossible-breakdown-warning">
1352+
<Alert
1353+
message={`Farmers would need a negative ${driverLabel} in order to hit the income target. This is not physically possible and the price breakdown is unavailable.`}
1354+
type="warning"
1355+
className="impossible-alert"
1356+
/>
1357+
</div>
1358+
);
1359+
}
1360+
13321361
// Use raw values for calculation but ensure breakdown logic
13331362
// If target is met, we might want to show the scenario breakdown instead of theoretical
13341363
// because theoretical breakdown for negative prices doesn't make sense visually.

0 commit comments

Comments
 (0)