Skip to content

Commit cc27178

Browse files
Update roi_calculator.html
1 parent 1ce77d4 commit cc27178

File tree

1 file changed

+77
-9
lines changed

1 file changed

+77
-9
lines changed

demos/roi_calculator.html

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>Ternary Logic Framework - Economic Impact Assessment.</title>
6+
<title>Ternary Logic Framework - Economic Impact Assessment</title>
77
<style>
88
* {
99
margin: 0;
@@ -734,9 +734,55 @@ <h2>Implementation Planning</h2>
734734
const domain = document.getElementById('domain').value;
735735
const employees = parseFloat(document.getElementById('employees').value);
736736

737+
// Input validation - check for out of bounds scenarios
738+
const totalDailyValue = decisions * avgValue;
739+
const maxSupportedValue = 1000000000000; // $1 trillion daily
740+
741+
if (totalDailyValue > maxSupportedValue || isNaN(totalDailyValue)) {
742+
// Show graceful error state
743+
document.getElementById('currentExposure').textContent = '—';
744+
document.getElementById('annualBenefit').textContent = '—';
745+
document.getElementById('qualityImprovement').textContent = 'Model out of range';
746+
document.getElementById('uncertainDecisions').textContent = '—';
747+
document.getElementById('totalInvestment').textContent = '—';
748+
document.getElementById('year1Net').textContent = '—';
749+
document.getElementById('roi1').textContent = 'Not applicable';
750+
document.getElementById('payback').textContent = 'Not applicable';
751+
document.getElementById('npv3').textContent = '—';
752+
document.getElementById('dailyOpp').textContent = '—';
753+
754+
// Show error message in breakdown table
755+
const tbody = document.getElementById('breakdownTable');
756+
tbody.innerHTML = `
757+
<tr>
758+
<td colspan="4" style="text-align: center; padding: 30px; color: #e67e22;">
759+
<strong>Scenario exceeds stability limits</strong><br>
760+
<span style="font-size: 0.9em; color: #7f8c8d;">
761+
Please adjust parameters. Daily transaction value exceeds supported range.<br>
762+
Current: ${formatCurrency(totalDailyValue)} | Maximum: ${formatCurrency(maxSupportedValue)}
763+
</span>
764+
</td>
765+
</tr>
766+
`;
767+
768+
// Update sector insights with warning
769+
const container = document.getElementById('sectorInsights');
770+
container.innerHTML = `
771+
<div class="insight-item" style="color: #e67e22;">
772+
When inputs exceed operational bounds, the framework maintains integrity by refusing to compute.
773+
</div>
774+
<div class="insight-item">
775+
Please normalize assumptions to realistic institutional parameters.
776+
</div>
777+
`;
778+
779+
// Show results section but with error state
780+
document.getElementById('results').classList.add('show');
781+
return;
782+
}
783+
737784
// Sanity checks to prevent astronomical numbers
738-
const maxDailyValue = decisions * avgValue;
739-
const maxReasonableExposure = maxDailyValue * 0.05; // Cap at 5% of daily volume
785+
const maxReasonableExposure = totalDailyValue * 0.05; // Cap at 5% of daily volume
740786

741787
// Calculate uncertain decisions
742788
const uncertainDecisions = decisions * uncertainty;
@@ -753,6 +799,17 @@ <h2>Implementation Planning</h2>
753799
const dailyExposure = uncertainDecisions * avgValue * errorCost * currentErrorRate;
754800
const annualExposure = Math.min(dailyExposure * workingDays, maxReasonableExposure * workingDays);
755801

802+
// Check for calculation validity
803+
if (isNaN(annualExposure) || annualExposure < 0 || !isFinite(annualExposure)) {
804+
// Graceful fallback for edge cases
805+
document.getElementById('currentExposure').textContent = '—';
806+
document.getElementById('annualBenefit').textContent = '—';
807+
document.getElementById('qualityImprovement').textContent = 'Insufficient data';
808+
document.getElementById('roi1').textContent = 'Not calculable';
809+
document.getElementById('results').classList.add('show');
810+
return;
811+
}
812+
756813
// Implementation costs based on REAL enterprise deployment
757814
const baseCost = Math.max(250000, employees * 150); // $150 per employee minimum
758815
const costs = {
@@ -825,7 +882,7 @@ <h2>Implementation Planning</h2>
825882

826883
// Calculate totals
827884
let totalCosts = costs.epistemic;
828-
let totalBenefits = benefits.epistemic;
885+
let totalBenefits = benefits.epistemic || 0;
829886

830887
Object.keys(pillars).forEach(key => {
831888
const pillarNum = key.replace('pillar', '');
@@ -836,18 +893,27 @@ <h2>Implementation Planning</h2>
836893
}
837894
});
838895

896+
// Validate final calculations
897+
if (!isFinite(totalBenefits) || !isFinite(totalCosts) || totalCosts === 0) {
898+
document.getElementById('currentExposure').textContent = '—';
899+
document.getElementById('annualBenefit').textContent = '—';
900+
document.getElementById('roi1').textContent = 'Not calculable';
901+
document.getElementById('results').classList.add('show');
902+
return;
903+
}
904+
839905
// Financial calculations
840906
const year1Net = totalBenefits - totalCosts;
841907
const roi1 = (year1Net / totalCosts) * 100;
842-
const paybackMonths = totalCosts / (totalBenefits / 12);
908+
const paybackMonths = totalBenefits > 0 ? (totalCosts / (totalBenefits / 12)) : 999;
843909

844910
// 3-year NPV at 10% discount
845911
let npv3 = -totalCosts;
846912
for (let year = 1; year <= 3; year++) {
847913
npv3 += totalBenefits / Math.pow(1.10, year);
848914
}
849915

850-
// Update display
916+
// Update display with validated values
851917
document.getElementById('currentExposure').textContent = formatCurrency(annualExposure);
852918
document.getElementById('annualBenefit').textContent = formatCurrency(totalBenefits);
853919
document.getElementById('qualityImprovement').textContent = (errorReduction * 100).toFixed(0) + '%';
@@ -859,10 +925,12 @@ <h2>Implementation Planning</h2>
859925
// Update ROI summary
860926
document.getElementById('totalInvestment').textContent = formatCurrency(totalCosts);
861927
document.getElementById('year1Net').textContent = formatCurrency(year1Net);
862-
document.getElementById('roi1').textContent = roi1.toFixed(0) + '%';
928+
document.getElementById('roi1').textContent = isFinite(roi1) ? roi1.toFixed(0) + '%' : 'Not applicable';
863929
document.getElementById('roi1').className = roi1 > 0 ? 'roi-metric-value good' : 'roi-metric-value warning';
864-
document.getElementById('payback').textContent = paybackMonths > 24 ? '>24 months' : paybackMonths.toFixed(1) + ' months';
865-
document.getElementById('npv3').textContent = formatCurrency(npv3);
930+
document.getElementById('payback').textContent = paybackMonths < 999 ?
931+
(paybackMonths > 24 ? '>24 months' : paybackMonths.toFixed(1) + ' months') :
932+
'Not applicable';
933+
document.getElementById('npv3').textContent = isFinite(npv3) ? formatCurrency(npv3) : '—';
866934
document.getElementById('dailyOpp').textContent = formatCurrency(annualExposure / workingDays);
867935

868936
// Update sector insights

0 commit comments

Comments
 (0)