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