mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Initialize git repository - Add comprehensive .gitignore for Go projects - Install golangci-lint v2.6.0 (latest v2) globally - Configure .golangci.yml with appropriate linters and formatters - Fix all formatting issues (gofmt) - Fix all errcheck issues (unchecked errors) - Adjust complexity threshold for validation functions - All checks passing: build, test, vet, lint
170 lines
5.3 KiB
Go
170 lines
5.3 KiB
Go
package scenarios
|
|
|
|
import (
|
|
"github.com/damirmukimov/city_resource_graph/models"
|
|
"github.com/damirmukimov/city_resource_graph/models/params"
|
|
)
|
|
|
|
// ScenarioResult contains the results of a scenario analysis.
|
|
type ScenarioResult struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Parameters ScenarioParams `json:"parameters"`
|
|
Result *models.ModelResult `json:"result"`
|
|
KeyMetrics KeyMetrics `json:"key_metrics"`
|
|
}
|
|
|
|
// ScenarioParams describes the parameter changes for a scenario.
|
|
type ScenarioParams struct {
|
|
AdoptionMultiplier float64 `json:"adoption_multiplier"` // Multiplier for adoption rates
|
|
PricingMultiplier float64 `json:"pricing_multiplier"` // Multiplier for pricing
|
|
CostMultiplier float64 `json:"cost_multiplier"` // Multiplier for costs
|
|
}
|
|
|
|
// KeyMetrics contains the most important metrics for comparison.
|
|
type KeyMetrics struct {
|
|
TotalRevenue float64 `json:"total_revenue"`
|
|
TotalCosts float64 `json:"total_costs"`
|
|
TotalProfit float64 `json:"total_profit"`
|
|
NPV float64 `json:"npv"`
|
|
IRR float64 `json:"irr"`
|
|
PaybackYears float64 `json:"payback_years"`
|
|
Year3Customers int `json:"year3_customers"`
|
|
Year3Revenue float64 `json:"year3_revenue"`
|
|
}
|
|
|
|
// RunSensitivityAnalysis runs multiple scenarios with parameter variations.
|
|
func RunSensitivityAnalysis(baseParams *params.Params) []ScenarioResult {
|
|
scenarios := []ScenarioResult{
|
|
{
|
|
Name: "Base Case",
|
|
Description: "Original parameters as configured",
|
|
Parameters: ScenarioParams{
|
|
AdoptionMultiplier: 1.0,
|
|
PricingMultiplier: 1.0,
|
|
CostMultiplier: 1.0,
|
|
},
|
|
},
|
|
{
|
|
Name: "Optimistic",
|
|
Description: "20% higher adoption, 10% higher pricing, 10% lower costs",
|
|
Parameters: ScenarioParams{
|
|
AdoptionMultiplier: 1.2,
|
|
PricingMultiplier: 1.1,
|
|
CostMultiplier: 0.9,
|
|
},
|
|
},
|
|
{
|
|
Name: "Conservative",
|
|
Description: "20% lower adoption, 10% lower pricing, 10% higher costs",
|
|
Parameters: ScenarioParams{
|
|
AdoptionMultiplier: 0.8,
|
|
PricingMultiplier: 0.9,
|
|
CostMultiplier: 1.1,
|
|
},
|
|
},
|
|
{
|
|
Name: "High Growth",
|
|
Description: "50% higher adoption, same pricing and costs",
|
|
Parameters: ScenarioParams{
|
|
AdoptionMultiplier: 1.5,
|
|
PricingMultiplier: 1.0,
|
|
CostMultiplier: 1.0,
|
|
},
|
|
},
|
|
{
|
|
Name: "Cost Focused",
|
|
Description: "Same adoption and pricing, 20% lower costs",
|
|
Parameters: ScenarioParams{
|
|
AdoptionMultiplier: 1.0,
|
|
PricingMultiplier: 1.0,
|
|
CostMultiplier: 0.8,
|
|
},
|
|
},
|
|
}
|
|
|
|
results := make([]ScenarioResult, len(scenarios))
|
|
|
|
for i, scenario := range scenarios {
|
|
// Create modified parameters for this scenario
|
|
scenarioParams := createScenarioParams(baseParams, scenario.Parameters)
|
|
|
|
// Run the model with modified parameters
|
|
result, err := models.Calculate(scenarioParams)
|
|
if err != nil {
|
|
// In a real implementation, you'd want to handle errors better
|
|
continue
|
|
}
|
|
|
|
// Extract key metrics
|
|
keyMetrics := extractKeyMetrics(result)
|
|
|
|
results[i] = ScenarioResult{
|
|
Name: scenario.Name,
|
|
Description: scenario.Description,
|
|
Parameters: scenario.Parameters,
|
|
Result: result,
|
|
KeyMetrics: keyMetrics,
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// createScenarioParams creates modified parameters for a scenario.
|
|
func createScenarioParams(base *params.Params, mods ScenarioParams) *params.Params {
|
|
// Create a deep copy of the base parameters
|
|
// For simplicity, we'll modify the key fields directly
|
|
// In a production system, you'd want proper deep copying
|
|
|
|
scenario := *base // Shallow copy
|
|
|
|
// Modify adoption rates
|
|
if mods.AdoptionMultiplier != 1.0 {
|
|
for yearStr, original := range base.Adoption.TotalOrgs {
|
|
scenario.Adoption.TotalOrgs[yearStr] = int(float64(original) * mods.AdoptionMultiplier)
|
|
}
|
|
}
|
|
|
|
// Modify pricing
|
|
if mods.PricingMultiplier != 1.0 {
|
|
scenario.Pricing.Basic = base.Pricing.Basic * mods.PricingMultiplier
|
|
scenario.Pricing.Business = base.Pricing.Business * mods.PricingMultiplier
|
|
scenario.Pricing.Enterprise = base.Pricing.Enterprise * mods.PricingMultiplier
|
|
}
|
|
|
|
// Modify costs
|
|
if mods.CostMultiplier != 1.0 {
|
|
for yearStr, engineers := range base.Costs.Engineers {
|
|
scenario.Costs.Engineers[yearStr] = int(float64(engineers) * mods.CostMultiplier)
|
|
}
|
|
for yearStr, infra := range base.Costs.Infrastructure {
|
|
scenario.Costs.Infrastructure[yearStr] = infra * mods.CostMultiplier
|
|
}
|
|
for yearStr, marketing := range base.Costs.MarketingSales {
|
|
scenario.Costs.MarketingSales[yearStr] = marketing * mods.CostMultiplier
|
|
}
|
|
for yearStr, ops := range base.Costs.Operations {
|
|
scenario.Costs.Operations[yearStr] = ops * mods.CostMultiplier
|
|
}
|
|
}
|
|
|
|
return &scenario
|
|
}
|
|
|
|
// extractKeyMetrics pulls the most important metrics from a model result.
|
|
func extractKeyMetrics(result *models.ModelResult) KeyMetrics {
|
|
year3 := result.Years[len(result.Years)-1] // Last year (Year 3)
|
|
|
|
return KeyMetrics{
|
|
TotalRevenue: result.Summary.TotalRevenue,
|
|
TotalCosts: result.Summary.TotalCosts,
|
|
TotalProfit: result.Summary.TotalProfit,
|
|
NPV: result.Profitability.NPV,
|
|
IRR: result.Profitability.IRR,
|
|
PaybackYears: result.Profitability.PaybackPeriod,
|
|
Year3Customers: year3.Customer.TotalOrgs,
|
|
Year3Revenue: year3.Revenue.Total,
|
|
}
|
|
}
|