UNPKG

monte-carlo-simulator

Version:

Business decision framework with Monte Carlo risk analysis - instant via npx

504 lines 25.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TemplateLibrary = void 0; const path_1 = __importDefault(require("path")); const fs_1 = require("fs"); const yaml_1 = __importDefault(require("yaml")); const schema_1 = require("../config/schema"); const resource_paths_1 = require("../utils/resource-paths"); class TemplateLibrary { templatesPath; templates = new Map(); validator; constructor() { // Use dynamic resource path resolution for NPX compatibility const resourcePaths = (0, resource_paths_1.getResourcePaths)(); this.templatesPath = resourcePaths.templates; this.validator = new schema_1.ConfigurationValidator(); } async loadTemplates() { try { const templateFiles = await fs_1.promises.readdir(this.templatesPath); const yamlFiles = templateFiles.filter(file => file.endsWith('.yaml') || file.endsWith('.yml')); for (const file of yamlFiles) { const templatePath = path_1.default.join(this.templatesPath, file); const validationResult = await this.validateTemplate(templatePath, file); if (validationResult.valid) { const template = this.createBusinessTemplate(validationResult.config, file); this.templates.set(template.info.id, template); } else { console.warn(`⚠️ Skipping template ${file}: ${validationResult.error}`); } } } catch (error) { // Templates directory not found - this is ok, just means no templates available } } /** * Comprehensive template validation with detailed error reporting */ async validateTemplate(templatePath, _filename) { try { // Step 1: YAML syntax validation const content = await fs_1.promises.readFile(templatePath, 'utf-8'); let config; try { config = yaml_1.default.parse(content); } catch (yamlError) { return { valid: false, error: `YAML syntax error - ${yamlError instanceof Error ? yamlError.message : 'Invalid YAML'}` }; } // Step 2: Schema validation using existing ConfigurationValidator const schemaValidation = this.validator.validateConfig(config); if (!schemaValidation.valid) { return { valid: false, error: `Schema validation failed - ${schemaValidation.errors.join(', ')}` }; } // Step 3: Business logic validation (if simulation logic exists) if (config.simulation?.logic) { const logicValidation = this.validateSimulationLogic(config.simulation.logic, config.parameters); if (!logicValidation.valid) { return { valid: false, error: `Logic validation failed - ${logicValidation.error}` }; } } return { valid: true, config }; } catch (error) { return { valid: false, error: `File read error - ${error instanceof Error ? error.message : 'Unknown error'}` }; } } /** * Validate simulation logic for common errors */ validateSimulationLogic(logic, parameters) { try { // Extract parameter names for validation const parameterNames = parameters.map(p => p.key); // Check for undefined function calls (common issue) if (logic.includes('round(') && !logic.includes('Math.round(')) { return { valid: false, error: 'Use Math.round() instead of round()' }; } // Remove comments and strings before analyzing variables const cleanedLogic = logic .replace(/\/\/.*$/gm, '') // Remove single-line comments .replace(/\/\*[\s\S]*?\*\//g, '') // Remove multi-line comments .replace(/"[^"]*"/g, '""') // Replace strings with empty strings .replace(/'[^']*'/g, "''"); // Replace single-quoted strings // Check for undefined variables by looking for parameter usage const variablePattern = /\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g; const usedVariables = [...cleanedLogic.matchAll(variablePattern)] .map(match => match[1]) .filter(name => !['Math', 'random', 'const', 'let', 'var', 'return', 'if', 'else', 'for', 'while', 'function', 'true', 'false', 'null', 'undefined'].includes(name) && !name.match(/^\d/) // not numbers ); const undefinedVariables = usedVariables.filter(variable => !parameterNames.includes(variable) && !cleanedLogic.includes(`const ${variable}`) && !cleanedLogic.includes(`let ${variable}`) && !cleanedLogic.includes(`var ${variable}`) && // Filter out object property names that are defined in the same scope !cleanedLogic.includes(`${variable}:`) && // Filter out known JavaScript methods !['min', 'max', 'pow', 'round', 'floor', 'ceil', 'abs'].includes(variable)); if (undefinedVariables.length > 0) { return { valid: false, error: `Undefined variables: ${undefinedVariables.join(', ')}. Available parameters: ${parameterNames.join(', ')}` }; } return { valid: true }; } catch (error) { return { valid: false, error: `Logic analysis failed - ${error instanceof Error ? error.message : 'Unknown error'}` }; } } createBusinessTemplate(config, filename) { const id = filename.replace(/\.(yaml|yml)$/, ''); return { config, info: { id, name: config.name, category: config.category, description: config.description, tags: config.tags || [], businessContext: this.extractBusinessContext(config), useCase: this.extractUseCase(config), industryRelevance: this.extractIndustryRelevance(config) }, guidance: { whenToUse: this.generateWhenToUse(config), parameterTips: this.generateParameterTips(config), businessInsights: this.generateBusinessInsights(config), industryBenchmarks: this.extractIndustryBenchmarks(config) }, businessIntelligence: this.generateBusinessIntelligence(config) }; } extractBusinessContext(config) { const category = config.category.toLowerCase(); const hasARR = config.parameters.some(p => p.key.toLowerCase().includes('annualrecurringrevenue')); if (hasARR) { return `ARR-based ${category} simulation with business intelligence metrics`; } const contextMap = { 'business': 'Strategic business planning and operational optimization', 'marketing': 'Marketing campaign performance and customer acquisition analysis', 'software': 'Software development project planning and resource allocation', 'e-commerce': 'E-commerce performance optimization and conversion analysis', 'manufacturing': 'Manufacturing capacity planning and operational efficiency', 'operations': 'Operational process improvement and resource optimization' }; return contextMap[category] || `${category} analysis and planning simulation`; } extractUseCase(config) { const name = config.name.toLowerCase(); if (name.includes('restaurant')) { return 'Restaurant investment planning, profitability analysis, and operational optimization'; } else if (name.includes('saas') || name.includes('growth')) { return 'SaaS business growth planning, unit economics optimization, and scaling strategy'; } else if (name.includes('marketing') || name.includes('campaign')) { return 'Marketing campaign ROI analysis, customer acquisition optimization, and budget allocation'; } else if (name.includes('software') || name.includes('project')) { return 'Software development project estimation, team scaling, and delivery planning'; } else if (name.includes('ecommerce') || name.includes('conversion')) { return 'E-commerce conversion optimization, customer journey analysis, and revenue improvement'; } else if (name.includes('manufacturing') || name.includes('capacity')) { return 'Manufacturing capacity planning, production optimization, and operational efficiency'; } return `${config.category} scenario analysis and strategic planning`; } extractIndustryRelevance(config) { const tags = config.tags || []; const name = config.name.toLowerCase(); const industries = []; if (tags.includes('restaurant') || name.includes('restaurant')) { industries.push('Hospitality', 'Food Service', 'Retail'); } if (tags.includes('saas') || name.includes('saas')) { industries.push('Software', 'Technology', 'B2B Services'); } if (tags.includes('marketing') || name.includes('marketing')) { industries.push('Advertising', 'Digital Marketing', 'E-commerce'); } if (tags.includes('manufacturing') || name.includes('manufacturing')) { industries.push('Manufacturing', 'Industrial', 'Supply Chain'); } if (tags.includes('software') || name.includes('software')) { industries.push('Technology', 'Software Development', 'IT Services'); } return industries.length > 0 ? industries : ['General Business']; } generateWhenToUse(config) { const category = config.category.toLowerCase(); const hasARR = config.parameters.some(p => p.key.toLowerCase().includes('annualrecurringrevenue')); if (hasARR) { return `Use when planning ${category} investments based on company ARR and need realistic business projections with industry KPIs`; } const whenToUseMap = { 'business': 'Use for strategic business planning, investment analysis, and operational decision-making', 'marketing': 'Use for marketing campaign planning, budget optimization, and ROI forecasting', 'software': 'Use for software project estimation, team planning, and delivery timeline analysis', 'e-commerce': 'Use for e-commerce optimization, conversion analysis, and revenue improvement planning', 'manufacturing': 'Use for capacity planning, production optimization, and operational efficiency analysis' }; return whenToUseMap[category] || `Use for ${category} analysis and strategic planning scenarios`; } generateParameterTips(config) { const tips = {}; config.parameters.forEach(param => { const key = param.key.toLowerCase(); if (key.includes('annualrecurringrevenue') || key.includes('arr')) { tips[param.key] = 'Use your actual company ARR. This drives realistic budget allocations across all business functions.'; } else if (key.includes('budget') && key.includes('percent')) { tips[param.key] = 'Industry benchmarks: B2B SaaS 8-15%, B2C 15-25%, Enterprise 5-12%'; } else if (key.includes('conversion') && key.includes('rate')) { tips[param.key] = 'Industry averages: E-commerce 2-4%, B2B SaaS 2-8%, Lead generation 1-3%'; } else if (key.includes('churn')) { tips[param.key] = 'Typical ranges: SMB 3-7%/month, Mid-market 1-3%/month, Enterprise 0.5-1%/month'; } else if (key.includes('team') && key.includes('size')) { tips[param.key] = 'Consider Brooks\' Law: teams >7 people have coordination overhead'; } else if (key.includes('capacity') && key.includes('utilization')) { tips[param.key] = 'Optimal utilization: Manufacturing 75-85%, Services 70-80%, avoid >90%'; } else if (key.includes('customer') && key.includes('acquisition')) { tips[param.key] = 'Target CAC:LTV ratio of 1:3 or better for sustainable growth'; } else if (key.includes('average') && key.includes('order')) { tips[param.key] = 'Track trends: seasonal variations, customer segment differences, product mix impact'; } else if (key.includes('traffic') || key.includes('visitors')) { tips[param.key] = 'Use actual analytics data. Consider seasonal patterns and growth trends'; } }); return tips; } generateBusinessInsights(config) { const insights = []; const name = config.name.toLowerCase(); if (name.includes('restaurant')) { insights.push('Food costs should typically stay below 32% of revenue', 'Labor costs generally range 25-35% of revenue depending on service model', 'Location quality has 2-3x impact on customer traffic and revenue', 'Table turnover rate directly impacts revenue per seat capacity'); } else if (name.includes('saas') || name.includes('growth')) { insights.push('Net Revenue Retention >100% indicates healthy expansion revenue', 'CAC Payback Period should be <12 months for efficient growth', 'Monthly churn compounds exponentially - small improvements have big impact', 'Product-led growth typically has lower CAC but requires higher product investment'); } else if (name.includes('marketing')) { insights.push('Multi-channel campaigns typically achieve 1.2-1.5x higher ROI than single-channel', 'Customer lifetime value must exceed acquisition cost by 3:1 minimum', 'Organic amplification from paid campaigns often provides 20-40% bonus reach', 'Brand impact compounds over time - consider long-term value beyond immediate ROI'); } else if (name.includes('software') || name.includes('project')) { insights.push('Team scaling follows Brooks\' Law - doubling team size rarely halves delivery time', 'Technical complexity has exponential impact on delivery timeline', 'Quality requirements significantly impact both timeline and cost', 'Risk buffers should increase with architectural complexity and team experience gaps'); } else if (name.includes('ecommerce') || name.includes('conversion')) { insights.push('Mobile conversion rates typically 30-50% lower than desktop', 'Checkout funnel optimization often provides highest ROI improvements', 'Customer lifetime value improvements compound through retention', 'Personalization can improve conversion rates 10-30% but requires significant investment'); } else if (name.includes('manufacturing')) { insights.push('Overall Equipment Effectiveness (OEE) >85% indicates world-class operations', 'Capacity utilization >90% often creates bottlenecks and quality issues', 'Automation ROI depends heavily on product complexity and volume', 'Lead time reduction often has greater business impact than cost reduction'); } return insights; } extractIndustryBenchmarks(config) { const benchmarks = {}; const name = config.name.toLowerCase(); if (name.includes('restaurant')) { benchmarks['Food Cost %'] = '28-35% of revenue'; benchmarks['Labor Cost %'] = '25-35% of revenue'; benchmarks['Net Profit Margin'] = '3-6% for restaurants'; benchmarks['Revenue per Seat'] = '$400-800/month depending on segment'; } else if (name.includes('saas')) { benchmarks['Net Revenue Retention'] = '>110% for healthy growth'; benchmarks['CAC Payback'] = '<12 months'; benchmarks['Gross Margin'] = '75-85% for SaaS'; benchmarks['Monthly Churn'] = 'SMB: 3-7%, Enterprise: 0.5-1%'; } else if (name.includes('marketing')) { benchmarks['B2B CAC'] = '$200-1500 depending on ACV'; benchmarks['B2C CAC'] = '$5-100 depending on LTV'; benchmarks['Email Marketing ROI'] = '36:1 average return'; benchmarks['Content Marketing ROI'] = '3:1 average return'; } return Object.keys(benchmarks).length > 0 ? benchmarks : undefined; } generateBusinessIntelligence(config) { const name = config.name.toLowerCase(); const tags = config.tags || []; const hasARR = config.parameters.some(p => p.key.toLowerCase().includes('annualrecurringrevenue')); // Determine industry categories const industries = []; if (name.includes('restaurant') || tags.includes('restaurant')) { industries.push('Hospitality', 'Food Service', 'Retail'); } if (name.includes('saas') || tags.includes('saas') || hasARR) { industries.push('Software', 'Technology', 'SaaS'); } if (name.includes('marketing') || tags.includes('marketing')) { industries.push('Marketing', 'Digital Marketing', 'E-commerce'); } if (name.includes('software') || tags.includes('software')) { industries.push('Technology', 'Software Development'); } if (name.includes('manufacturing')) { industries.push('Manufacturing', 'Industrial'); } if (industries.length === 0) { industries.push('General Business'); } // Determine business model let businessModel = 'B2B'; if (name.includes('saas') || hasARR) { businessModel = 'SaaS'; } else if (name.includes('b2c') || name.includes('consumer') || name.includes('restaurant')) { businessModel = 'B2C'; } else if (name.includes('marketplace') || name.includes('platform')) { businessModel = 'Marketplace'; } // Determine decision type let decisionType = 'operational'; if (name.includes('investment') || name.includes('roi')) { decisionType = 'investment'; } else if (name.includes('strategic') || name.includes('scaling')) { decisionType = 'strategic'; } else if (name.includes('campaign') || name.includes('marketing')) { decisionType = 'tactical'; } // Determine risk profile let riskProfile = 'medium'; if (name.includes('investment') || name.includes('scaling') || name.includes('software')) { riskProfile = 'high'; } else if (name.includes('marketing') || name.includes('campaign')) { riskProfile = 'medium'; } else if (name.includes('simple') || name.includes('basic')) { riskProfile = 'low'; } // Determine time horizon let timeHorizon = 'medium'; const hasLongTermMetrics = config.parameters.some(p => p.key.toLowerCase().includes('lifetime') || p.key.toLowerCase().includes('annual') || p.description?.toLowerCase().includes('year')); if (hasLongTermMetrics || name.includes('investment')) { timeHorizon = 'long'; } else if (name.includes('campaign') || name.includes('tactical')) { timeHorizon = 'short'; } // Generate KPI categories const kpiCategories = []; if (name.includes('roi') || name.includes('investment')) { kpiCategories.push('Financial', 'ROI', 'Profitability'); } if (name.includes('marketing') || name.includes('customer')) { kpiCategories.push('Customer Acquisition', 'Marketing Performance'); } if (name.includes('team') || name.includes('scaling')) { kpiCategories.push('Operational Efficiency', 'Team Performance'); } if (name.includes('software') || name.includes('technology')) { kpiCategories.push('Technology ROI', 'Productivity'); } if (kpiCategories.length === 0) { kpiCategories.push('Business Performance', 'Financial'); } // Generate agent optimization keywords const keywords = []; keywords.push(...tags); if (name.includes('marketing')) keywords.push('marketing', 'campaign', 'acquisition', 'roi'); if (name.includes('investment')) keywords.push('investment', 'roi', 'payback', 'npv'); if (name.includes('team') || name.includes('scaling')) keywords.push('team', 'scaling', 'hiring', 'growth'); if (name.includes('software')) keywords.push('software', 'technology', 'productivity', 'automation'); if (hasARR) keywords.push('arr', 'saas', 'recurring', 'subscription'); // Generate context hints for agent optimization const contextHints = []; if (businessModel === 'SaaS') { contextHints.push('ARR-driven budgeting', 'Subscription metrics', 'Recurring revenue models'); } if (decisionType === 'investment') { contextHints.push('ROI calculations', 'Payback periods', 'Risk-adjusted returns'); } if (name.includes('marketing')) { contextHints.push('Customer acquisition costs', 'Lifetime value optimization', 'Channel performance'); } // Parameter priority for agent suggestions const parameterPriority = []; const arrParam = config.parameters.find(p => p.key.toLowerCase().includes('annualrecurringrevenue')); if (arrParam) parameterPriority.push(arrParam.key); const budgetParams = config.parameters.filter(p => p.key.toLowerCase().includes('budget') || p.key.toLowerCase().includes('investment') || p.key.toLowerCase().includes('cost')); parameterPriority.push(...budgetParams.map(p => p.key)); return { industry: industries, businessModel, decisionType, riskProfile, timeHorizon, kpiCategories, agentOptimization: { keywords: [...new Set(keywords)], // Remove duplicates contextHints, parameterPriority } }; } getTemplatesByCategory(category) { return Array.from(this.templates.values()) .filter(template => template.info.category.toLowerCase() === category.toLowerCase()); } getTemplatesByTag(tag) { return Array.from(this.templates.values()) .filter(template => template.info.tags.includes(tag)); } getTemplate(id) { return this.templates.get(id); } getAllTemplates() { return Array.from(this.templates.values()); } getTemplateCategories() { const categories = new Set(); this.templates.forEach(template => categories.add(template.info.category)); return Array.from(categories).sort(); } searchTemplates(query) { const searchTerm = query.toLowerCase(); return Array.from(this.templates.values()).filter(template => template.info.name.toLowerCase().includes(searchTerm) || template.info.description.toLowerCase().includes(searchTerm) || template.info.tags.some(tag => tag.toLowerCase().includes(searchTerm)) || template.info.businessContext.toLowerCase().includes(searchTerm)); } generateBusinessGuidance(template) { const guidance = [ `📋 ${template.info.name}`, '', `🎯 Use Case: ${template.info.useCase}`, `🏢 Industries: ${template.info.industryRelevance.join(', ')}`, '', `💡 When to Use:`, template.guidance.whenToUse, '' ]; if (Object.keys(template.guidance.parameterTips).length > 0) { guidance.push('🔧 Parameter Tips:'); Object.entries(template.guidance.parameterTips).forEach(([key, tip]) => { guidance.push(` • ${key}: ${tip}`); }); guidance.push(''); } if (template.guidance.businessInsights.length > 0) { guidance.push('📊 Key Business Insights:'); template.guidance.businessInsights.forEach(insight => { guidance.push(` • ${insight}`); }); guidance.push(''); } if (template.guidance.industryBenchmarks) { guidance.push('📈 Industry Benchmarks:'); Object.entries(template.guidance.industryBenchmarks).forEach(([metric, benchmark]) => { guidance.push(` • ${metric}: ${benchmark}`); }); guidance.push(''); } return guidance.join('\n'); } } exports.TemplateLibrary = TemplateLibrary; //# sourceMappingURL=template-library.js.map