more realistics numbers in the roi calculator
This commit is contained in:
parent
07df4336e9
commit
86d4b6412e
3 changed files with 207 additions and 130 deletions
|
|
@ -8,34 +8,34 @@ class ROICalculator {
|
|||
conservative: {
|
||||
name: 'Conservative',
|
||||
enabled: true,
|
||||
churnRate: 0.02,
|
||||
churnRate: 0.025, // Lower churn with sticky managed services
|
||||
phases: [
|
||||
{ months: 6, newInstancesPerMonth: 50 },
|
||||
{ months: 6, newInstancesPerMonth: 75 },
|
||||
{ months: 12, newInstancesPerMonth: 100 },
|
||||
{ months: 12, newInstancesPerMonth: 150 }
|
||||
{ months: 6, newInstancesPerMonth: 15 }, // 5 new clients × 3 instances each
|
||||
{ months: 6, newInstancesPerMonth: 24 }, // 6 new clients × 4 instances (growth + expansion)
|
||||
{ months: 12, newInstancesPerMonth: 35 }, // 7 new clients × 5 instances (mature usage)
|
||||
{ months: 12, newInstancesPerMonth: 40 } // 8 new clients × 5 instances
|
||||
]
|
||||
},
|
||||
moderate: {
|
||||
name: 'Moderate',
|
||||
enabled: true,
|
||||
churnRate: 0.03,
|
||||
churnRate: 0.03, // Balanced churn with growth
|
||||
phases: [
|
||||
{ months: 6, newInstancesPerMonth: 100 },
|
||||
{ months: 6, newInstancesPerMonth: 200 },
|
||||
{ months: 12, newInstancesPerMonth: 300 },
|
||||
{ months: 12, newInstancesPerMonth: 400 }
|
||||
{ months: 6, newInstancesPerMonth: 25 }, // 8 new clients × 3 instances each
|
||||
{ months: 6, newInstancesPerMonth: 45 }, // 10 new clients × 4.5 instances (expansion)
|
||||
{ months: 12, newInstancesPerMonth: 70 }, // 12 new clients × 6 instances (diverse services)
|
||||
{ months: 12, newInstancesPerMonth: 90 } // 15 new clients × 6 instances
|
||||
]
|
||||
},
|
||||
aggressive: {
|
||||
name: 'Aggressive',
|
||||
enabled: true,
|
||||
churnRate: 0.05,
|
||||
churnRate: 0.035, // Slightly higher churn with rapid growth
|
||||
phases: [
|
||||
{ months: 6, newInstancesPerMonth: 200 },
|
||||
{ months: 6, newInstancesPerMonth: 400 },
|
||||
{ months: 12, newInstancesPerMonth: 600 },
|
||||
{ months: 12, newInstancesPerMonth: 800 }
|
||||
{ months: 6, newInstancesPerMonth: 40 }, // 12 new clients × 3.5 instances
|
||||
{ months: 6, newInstancesPerMonth: 80 }, // 16 new clients × 5 instances (viral growth)
|
||||
{ months: 12, newInstancesPerMonth: 120 }, // 20 new clients × 6 instances (full adoption)
|
||||
{ months: 12, newInstancesPerMonth: 150 } // 25 new clients × 6 instances
|
||||
]
|
||||
}
|
||||
};
|
||||
|
|
@ -134,8 +134,8 @@ class ROICalculator {
|
|||
}
|
||||
}
|
||||
|
||||
// Enhanced investment scaling factor (only for direct investment)
|
||||
// Exponential scaling provides strong incentives for larger investments
|
||||
// Market-realistic investment scaling factor (only for direct investment)
|
||||
// Conservative scaling based on industry standards and economies of scale
|
||||
const baseInvestment = 500000;
|
||||
let investmentScaleFactor;
|
||||
let churnReductionFactor;
|
||||
|
|
@ -148,47 +148,46 @@ class ROICalculator {
|
|||
revenueMultiplier = 1.0;
|
||||
acceleratedBreakEvenFactor = 1.0;
|
||||
} else {
|
||||
// Exponential scaling for better ROI at higher investments
|
||||
// Conservative linear scaling with market-realistic caps
|
||||
if (inputs.investmentAmount <= baseInvestment) {
|
||||
investmentScaleFactor = inputs.investmentAmount / baseInvestment;
|
||||
} else if (inputs.investmentAmount <= 1000000) {
|
||||
// 500k to 1M: Exponential scaling (1.0x to 2.2x)
|
||||
// 500k to 1M: Moderate linear scaling (1.0x to 1.5x)
|
||||
const ratio = inputs.investmentAmount / baseInvestment;
|
||||
investmentScaleFactor = Math.pow(ratio, 1.2);
|
||||
investmentScaleFactor = 1.0 + ((ratio - 1.0) * 0.5);
|
||||
} else if (inputs.investmentAmount <= 1500000) {
|
||||
// 1M to 1.5M: Enhanced exponential scaling (2.2x to 3.5x)
|
||||
const ratio = inputs.investmentAmount / baseInvestment;
|
||||
investmentScaleFactor = Math.pow(ratio, 1.3);
|
||||
// 1M to 1.5M: Conservative scaling (1.5x to 1.8x)
|
||||
const progress = (inputs.investmentAmount - 1000000) / 500000;
|
||||
investmentScaleFactor = 1.5 + (progress * 0.3);
|
||||
} else {
|
||||
// 1.5M to 2M: Maximum exponential scaling (3.5x to 5.0x)
|
||||
const ratio = inputs.investmentAmount / baseInvestment;
|
||||
investmentScaleFactor = Math.pow(ratio, 1.4);
|
||||
// 1.5M to 2M: Maximum realistic scaling (1.8x to 2.0x)
|
||||
const progress = (inputs.investmentAmount - 1500000) / 500000;
|
||||
investmentScaleFactor = 1.8 + (progress * 0.2);
|
||||
}
|
||||
|
||||
// Revenue multipliers for large investments (economies of scale)
|
||||
// Market-sustainable revenue premiums (10-20% max)
|
||||
if (inputs.investmentAmount >= 2000000) {
|
||||
revenueMultiplier = 1.6; // 60% premium per instance
|
||||
revenueMultiplier = 1.2; // 20% premium - maximum sustainable
|
||||
} else if (inputs.investmentAmount >= 1500000) {
|
||||
revenueMultiplier = 1.4; // 40% premium per instance
|
||||
revenueMultiplier = 1.15; // 15% premium
|
||||
} else if (inputs.investmentAmount >= 1000000) {
|
||||
revenueMultiplier = 1.2; // 20% premium per instance
|
||||
revenueMultiplier = 1.1; // 10% premium
|
||||
} else {
|
||||
revenueMultiplier = 1.0; // No premium
|
||||
}
|
||||
|
||||
// Accelerated break-even for large investments
|
||||
// Modest break-even improvements (not dramatic acceleration)
|
||||
if (inputs.investmentAmount >= 1500000) {
|
||||
acceleratedBreakEvenFactor = 1.4; // 40% faster break-even
|
||||
acceleratedBreakEvenFactor = 1.15; // 15% faster break-even
|
||||
} else if (inputs.investmentAmount >= 1000000) {
|
||||
acceleratedBreakEvenFactor = 1.2; // 20% faster break-even
|
||||
acceleratedBreakEvenFactor = 1.1; // 10% faster break-even
|
||||
} else {
|
||||
acceleratedBreakEvenFactor = 1.0; // Standard break-even
|
||||
}
|
||||
|
||||
// Enhanced churn reduction with aggressive scaling
|
||||
// Higher investment = significantly better customer success = much lower churn
|
||||
// Realistic churn reduction based on customer success investments
|
||||
const churnReductionRatio = Math.min((inputs.investmentAmount - baseInvestment) / 1500000, 1.0);
|
||||
churnReductionFactor = Math.max(0.4, 1 - (churnReductionRatio * 0.6)); // Up to 60% churn reduction
|
||||
churnReductionFactor = Math.max(0.75, 1 - (churnReductionRatio * 0.25)); // Up to 25% churn reduction
|
||||
}
|
||||
|
||||
// Calculate adjusted churn rate with investment-based reduction
|
||||
|
|
@ -201,18 +200,18 @@ class ROICalculator {
|
|||
let cumulativeServalaRevenue = 0;
|
||||
let breakEvenMonth = null;
|
||||
|
||||
// Calculate enhanced grace period based on investment size
|
||||
// Calculate commercially viable grace period based on investment size
|
||||
const baseGracePeriod = inputs.gracePeriod;
|
||||
let gracePeriodBonus;
|
||||
if (inputs.investmentAmount >= 1500000) {
|
||||
gracePeriodBonus = 12; // 12 months extra for large investments
|
||||
gracePeriodBonus = 3; // 3 months extra for large investments
|
||||
} else if (inputs.investmentAmount >= 1000000) {
|
||||
gracePeriodBonus = 6; // 6 months extra for medium investments
|
||||
gracePeriodBonus = 2; // 2 months extra for medium investments
|
||||
} else {
|
||||
gracePeriodBonus = Math.floor((inputs.investmentAmount - baseInvestment) / 250000);
|
||||
gracePeriodBonus = Math.floor((inputs.investmentAmount - baseInvestment) / 500000); // More conservative bonus calculation
|
||||
}
|
||||
const effectiveGracePeriod = inputs.investmentModel === 'loan' ? 0 :
|
||||
Math.min(baseGracePeriod + gracePeriodBonus, Math.floor(totalMonths * 0.6)); // Up to 60% of timeframe
|
||||
Math.min(baseGracePeriod + gracePeriodBonus, 6); // Maximum 6 months grace period
|
||||
|
||||
// Track baseline performance for performance bonuses (direct investment only)
|
||||
let baselineInstances = 0; // Will track expected instances without performance scaling
|
||||
|
|
@ -262,16 +261,16 @@ class ROICalculator {
|
|||
const coreRevenue = baseCoreRevenue * revenueMultiplier;
|
||||
monthlyRevenue = serviceRevenue;
|
||||
|
||||
// Calculate scaled performance bonus based on investment size
|
||||
// Calculate realistic performance bonus based on investment size
|
||||
let maxPerformanceBonus;
|
||||
if (inputs.investmentAmount >= 2000000) {
|
||||
maxPerformanceBonus = 0.35; // 35% max bonus for largest investments
|
||||
maxPerformanceBonus = 0.15; // 15% max bonus for largest investments
|
||||
} else if (inputs.investmentAmount >= 1500000) {
|
||||
maxPerformanceBonus = 0.25; // 25% max bonus for large investments
|
||||
maxPerformanceBonus = 0.12; // 12% max bonus for large investments
|
||||
} else if (inputs.investmentAmount >= 1000000) {
|
||||
maxPerformanceBonus = 0.20; // 20% max bonus for medium investments
|
||||
maxPerformanceBonus = 0.10; // 10% max bonus for medium investments
|
||||
} else {
|
||||
maxPerformanceBonus = 0.15; // 15% max bonus for base investments
|
||||
maxPerformanceBonus = 0.08; // 8% max bonus for base investments
|
||||
}
|
||||
|
||||
// Calculate performance bonus if CSP exceeds baseline expectations
|
||||
|
|
@ -393,9 +392,9 @@ class ROICalculator {
|
|||
revenueMultiplier: revenueMultiplier,
|
||||
acceleratedBreakEvenFactor: acceleratedBreakEvenFactor,
|
||||
maxPerformanceBonus: inputs.investmentModel === 'direct' ?
|
||||
(inputs.investmentAmount >= 2000000 ? 35 :
|
||||
inputs.investmentAmount >= 1500000 ? 25 :
|
||||
inputs.investmentAmount >= 1000000 ? 20 : 15) : 0,
|
||||
(inputs.investmentAmount >= 2000000 ? 15 :
|
||||
inputs.investmentAmount >= 1500000 ? 12 :
|
||||
inputs.investmentAmount >= 1000000 ? 10 : 8) : 0,
|
||||
adjustedChurnRate: adjustedChurnRate * 100,
|
||||
performanceMultiplier: baselineInstances > 0 ? (currentInstances / baselineInstances) : 1.0
|
||||
};
|
||||
|
|
|
|||
|
|
@ -132,55 +132,55 @@ class ROICalculatorApp {
|
|||
const investmentAmount = inputs.investmentAmount;
|
||||
const baseInvestment = 500000;
|
||||
|
||||
// Calculate instance scaling factor
|
||||
// Calculate market-realistic instance scaling factor
|
||||
let scalingFactor;
|
||||
if (investmentAmount <= baseInvestment) {
|
||||
scalingFactor = investmentAmount / baseInvestment;
|
||||
} else if (investmentAmount <= 1000000) {
|
||||
const ratio = investmentAmount / baseInvestment;
|
||||
scalingFactor = Math.pow(ratio, 1.2);
|
||||
scalingFactor = 1.0 + ((ratio - 1.0) * 0.5); // Linear scaling to 1.5x
|
||||
} else if (investmentAmount <= 1500000) {
|
||||
const ratio = investmentAmount / baseInvestment;
|
||||
scalingFactor = Math.pow(ratio, 1.3);
|
||||
const progress = (investmentAmount - 1000000) / 500000;
|
||||
scalingFactor = 1.5 + (progress * 0.3); // Up to 1.8x
|
||||
} else {
|
||||
const ratio = investmentAmount / baseInvestment;
|
||||
scalingFactor = Math.pow(ratio, 1.4);
|
||||
const progress = (investmentAmount - 1500000) / 500000;
|
||||
scalingFactor = 1.8 + (progress * 0.2); // Max 2.0x
|
||||
}
|
||||
|
||||
// Calculate revenue premium
|
||||
// Calculate sustainable revenue premium
|
||||
let revenuePremium;
|
||||
if (investmentAmount >= 2000000) {
|
||||
revenuePremium = 60;
|
||||
revenuePremium = 20; // Maximum 20% premium
|
||||
} else if (investmentAmount >= 1500000) {
|
||||
revenuePremium = 40;
|
||||
revenuePremium = 15; // 15% premium
|
||||
} else if (investmentAmount >= 1000000) {
|
||||
revenuePremium = 20;
|
||||
revenuePremium = 10; // 10% premium
|
||||
} else {
|
||||
revenuePremium = 0;
|
||||
}
|
||||
|
||||
// Calculate grace period
|
||||
// Calculate commercially viable grace period
|
||||
const baseGracePeriod = inputs.gracePeriod;
|
||||
let gracePeriodBonus;
|
||||
if (investmentAmount >= 1500000) {
|
||||
gracePeriodBonus = 12;
|
||||
gracePeriodBonus = 3; // 3 months max bonus
|
||||
} else if (investmentAmount >= 1000000) {
|
||||
gracePeriodBonus = 6;
|
||||
gracePeriodBonus = 2; // 2 months bonus
|
||||
} else {
|
||||
gracePeriodBonus = Math.floor((investmentAmount - baseInvestment) / 250000);
|
||||
gracePeriodBonus = Math.floor((investmentAmount - baseInvestment) / 500000);
|
||||
}
|
||||
const totalGracePeriod = Math.max(0, baseGracePeriod + gracePeriodBonus);
|
||||
const totalGracePeriod = Math.min(Math.max(0, baseGracePeriod + gracePeriodBonus), 6); // Max 6 months
|
||||
|
||||
// Calculate max performance bonus
|
||||
// Calculate realistic max performance bonus
|
||||
let maxBonus;
|
||||
if (investmentAmount >= 2000000) {
|
||||
maxBonus = 35;
|
||||
maxBonus = 15; // 15% max bonus
|
||||
} else if (investmentAmount >= 1500000) {
|
||||
maxBonus = 25;
|
||||
maxBonus = 12; // 12% max bonus
|
||||
} else if (investmentAmount >= 1000000) {
|
||||
maxBonus = 20;
|
||||
maxBonus = 10; // 10% max bonus
|
||||
} else {
|
||||
maxBonus = 15;
|
||||
maxBonus = 8; // 8% max bonus
|
||||
}
|
||||
|
||||
// Update UI elements
|
||||
|
|
@ -411,49 +411,49 @@ class ROICalculatorApp {
|
|||
if (!this.calculator) return;
|
||||
|
||||
// Reset Conservative
|
||||
this.calculator.scenarios.conservative.churnRate = 0.02;
|
||||
this.calculator.scenarios.conservative.churnRate = 0.025;
|
||||
this.calculator.scenarios.conservative.phases = [
|
||||
{ months: 6, newInstancesPerMonth: 50 },
|
||||
{ months: 6, newInstancesPerMonth: 75 },
|
||||
{ months: 12, newInstancesPerMonth: 100 },
|
||||
{ months: 12, newInstancesPerMonth: 150 }
|
||||
{ months: 6, newInstancesPerMonth: 15 },
|
||||
{ months: 6, newInstancesPerMonth: 24 },
|
||||
{ months: 12, newInstancesPerMonth: 35 },
|
||||
{ months: 12, newInstancesPerMonth: 40 }
|
||||
];
|
||||
|
||||
// Reset Moderate
|
||||
this.calculator.scenarios.moderate.churnRate = 0.03;
|
||||
this.calculator.scenarios.moderate.phases = [
|
||||
{ months: 6, newInstancesPerMonth: 100 },
|
||||
{ months: 6, newInstancesPerMonth: 200 },
|
||||
{ months: 12, newInstancesPerMonth: 300 },
|
||||
{ months: 12, newInstancesPerMonth: 400 }
|
||||
{ months: 6, newInstancesPerMonth: 25 },
|
||||
{ months: 6, newInstancesPerMonth: 45 },
|
||||
{ months: 12, newInstancesPerMonth: 70 },
|
||||
{ months: 12, newInstancesPerMonth: 90 }
|
||||
];
|
||||
|
||||
// Reset Aggressive
|
||||
this.calculator.scenarios.aggressive.churnRate = 0.05;
|
||||
this.calculator.scenarios.aggressive.churnRate = 0.035;
|
||||
this.calculator.scenarios.aggressive.phases = [
|
||||
{ months: 6, newInstancesPerMonth: 200 },
|
||||
{ months: 6, newInstancesPerMonth: 400 },
|
||||
{ months: 12, newInstancesPerMonth: 600 },
|
||||
{ months: 12, newInstancesPerMonth: 800 }
|
||||
{ months: 6, newInstancesPerMonth: 40 },
|
||||
{ months: 6, newInstancesPerMonth: 80 },
|
||||
{ months: 12, newInstancesPerMonth: 120 },
|
||||
{ months: 12, newInstancesPerMonth: 150 }
|
||||
];
|
||||
|
||||
// Update UI inputs
|
||||
const inputMappings = [
|
||||
['conservative-churn', '2.0'],
|
||||
['conservative-phase-0', '50'],
|
||||
['conservative-phase-1', '75'],
|
||||
['conservative-phase-2', '100'],
|
||||
['conservative-phase-3', '150'],
|
||||
['conservative-churn', '2.5'],
|
||||
['conservative-phase-0', '15'],
|
||||
['conservative-phase-1', '24'],
|
||||
['conservative-phase-2', '35'],
|
||||
['conservative-phase-3', '40'],
|
||||
['moderate-churn', '3.0'],
|
||||
['moderate-phase-0', '100'],
|
||||
['moderate-phase-1', '200'],
|
||||
['moderate-phase-2', '300'],
|
||||
['moderate-phase-3', '400'],
|
||||
['aggressive-churn', '5.0'],
|
||||
['aggressive-phase-0', '200'],
|
||||
['aggressive-phase-1', '400'],
|
||||
['aggressive-phase-2', '600'],
|
||||
['aggressive-phase-3', '800']
|
||||
['moderate-phase-0', '25'],
|
||||
['moderate-phase-1', '45'],
|
||||
['moderate-phase-2', '70'],
|
||||
['moderate-phase-3', '90'],
|
||||
['aggressive-churn', '3.5'],
|
||||
['aggressive-phase-0', '40'],
|
||||
['aggressive-phase-1', '80'],
|
||||
['aggressive-phase-2', '120'],
|
||||
['aggressive-phase-3', '150']
|
||||
];
|
||||
|
||||
inputMappings.forEach(([id, value]) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue