mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Reorganized funding program structure: moved standalone .md files into organized directories with PROGRAM_INFO.md and APPLICATION_SCOPE.md - Created budget files for selected priority programs: * EIC Accelerator: budget_breakdown.csv and budget_justification.md (€1.815M) * ZIM: budget_breakdown.csv and budget_justification.md (€465k) * DBU: budget_breakdown.csv and budget_justification.md (€152.5k) * LIFE Programme: budget_breakdown.csv and budget_justification.md (€1.815M) - Created team CV files for all selected programs (CV_Damir_Mukimov.md) - Added application documents structure: * funding/applications/budget/ - Master budget files and templates * funding/applications/team_cvs/ - Master CV and team expertise summary - Updated FUNDING_GAP_ANALYSIS.md to reflect completed documents - Added APPLICATION_REQUIREMENTS_REPORT.md with detailed requirements - Added PREPARATION_PRIORITY.md for application preparation workflow
125 lines
6.1 KiB
Go
125 lines
6.1 KiB
Go
package team
|
|
|
|
import (
|
|
"github.com/damirmukimov/city_resource_graph/models/params"
|
|
)
|
|
|
|
// TeamMember represents a single team member with role and salary.
|
|
type TeamMember struct {
|
|
Role string `json:"role" yaml:"role"` // e.g., "backend_engineer", "frontend_engineer"
|
|
Salary float64 `json:"salary" yaml:"salary"` // Annual salary in EUR
|
|
}
|
|
|
|
// TeamComposition defines team composition for a given year.
|
|
type TeamComposition struct {
|
|
BackendEngineers int `json:"backend_engineers" yaml:"backend_engineers"` // Number of backend engineers
|
|
FrontendEngineers int `json:"frontend_engineers" yaml:"frontend_engineers"` // Number of frontend engineers
|
|
DevOpsEngineers int `json:"devops_engineers" yaml:"devops_engineers"` // Number of DevOps engineers
|
|
DataEngineers int `json:"data_engineers" yaml:"data_engineers"` // Number of data engineers
|
|
CTO int `json:"cto" yaml:"cto"` // Number of CTOs (typically 1)
|
|
BDSales int `json:"bd_sales" yaml:"bd_sales"` // Number of BD/Sales managers
|
|
DomainExperts int `json:"domain_experts" yaml:"domain_experts"` // Number of domain experts
|
|
CustomerSuccess int `json:"customer_success" yaml:"customer_success"` // Number of customer success
|
|
Operations int `json:"operations" yaml:"operations"` // Number of operations staff
|
|
Total int `json:"total" yaml:"total"` // Total team size
|
|
}
|
|
|
|
// Salaries defines annual salary for each role.
|
|
type Salaries struct {
|
|
BackendEngineer float64 `json:"backend_engineer" yaml:"backend_engineer"` // Annual salary in EUR
|
|
FrontendEngineer float64 `json:"frontend_engineer" yaml:"frontend_engineer"` // Annual salary in EUR
|
|
DevOpsEngineer float64 `json:"devops_engineer" yaml:"devops_engineer"` // Annual salary in EUR
|
|
DataEngineer float64 `json:"data_engineer" yaml:"data_engineer"` // Annual salary in EUR
|
|
CTO float64 `json:"cto" yaml:"cto"` // Annual salary in EUR
|
|
BDSales float64 `json:"bd_sales" yaml:"bd_sales"` // Annual salary in EUR
|
|
DomainExpert float64 `json:"domain_expert" yaml:"domain_expert"` // Annual salary in EUR
|
|
CustomerSuccess float64 `json:"customer_success" yaml:"customer_success"` // Annual salary in EUR
|
|
Operations float64 `json:"operations" yaml:"operations"` // Annual salary in EUR
|
|
}
|
|
|
|
// DefaultSalaries returns default salaries for each role.
|
|
func DefaultSalaries() Salaries {
|
|
return Salaries{
|
|
BackendEngineer: 100000, // €100k/year
|
|
FrontendEngineer: 100000, // €100k/year
|
|
DevOpsEngineer: 100000, // €100k/year
|
|
DataEngineer: 100000, // €100k/year
|
|
CTO: 120000, // €120k/year
|
|
BDSales: 100000, // €100k/year
|
|
DomainExpert: 90000, // €90k/year
|
|
CustomerSuccess: 70000, // €70k/year
|
|
Operations: 70000, // €70k/year
|
|
}
|
|
}
|
|
|
|
// CalculateTeamCosts computes total personnel costs for a team composition.
|
|
func CalculateTeamCosts(composition TeamComposition, salaries Salaries) float64 {
|
|
var total float64
|
|
|
|
total += float64(composition.BackendEngineers) * salaries.BackendEngineer
|
|
total += float64(composition.FrontendEngineers) * salaries.FrontendEngineer
|
|
total += float64(composition.DevOpsEngineers) * salaries.DevOpsEngineer
|
|
total += float64(composition.DataEngineers) * salaries.DataEngineer
|
|
total += float64(composition.CTO) * salaries.CTO
|
|
total += float64(composition.BDSales) * salaries.BDSales
|
|
total += float64(composition.DomainExperts) * salaries.DomainExpert
|
|
total += float64(composition.CustomerSuccess) * salaries.CustomerSuccess
|
|
total += float64(composition.Operations) * salaries.Operations
|
|
|
|
return total
|
|
}
|
|
|
|
// CalculateTeamCostsFromParams computes team costs using params structure.
|
|
// This bridges the old CostParams (engineers count + salary) to new team structure.
|
|
func CalculateTeamCostsFromParams(year int, p *params.Params, salaries Salaries) (float64, TeamComposition) {
|
|
// Get total engineers from params
|
|
totalEngineers := p.Costs.Engineers.GetYear(year)
|
|
|
|
// Default distribution (can be overridden in params.yaml)
|
|
composition := TeamComposition{
|
|
BackendEngineers: int(float64(totalEngineers) * 0.5), // 50% backend
|
|
FrontendEngineers: int(float64(totalEngineers) * 0.25), // 25% frontend
|
|
DevOpsEngineers: int(float64(totalEngineers) * 0.125), // 12.5% DevOps
|
|
DataEngineers: int(float64(totalEngineers) * 0.125), // 12.5% data
|
|
CTO: 1, // 1 CTO
|
|
BDSales: 1, // 1 BD/Sales
|
|
DomainExperts: 2, // 2 domain experts
|
|
CustomerSuccess: 0, // 0 initially, grows over time
|
|
Operations: 0, // 0 initially
|
|
}
|
|
|
|
// Adjust to match total engineers (distribute remaining)
|
|
allocated := composition.BackendEngineers + composition.FrontendEngineers +
|
|
composition.DevOpsEngineers + composition.DataEngineers
|
|
if allocated < totalEngineers {
|
|
// Add remaining to backend engineers
|
|
composition.BackendEngineers += totalEngineers - allocated
|
|
}
|
|
|
|
composition.Total = totalEngineers + composition.CTO + composition.BDSales +
|
|
composition.DomainExperts + composition.CustomerSuccess + composition.Operations
|
|
|
|
// Calculate costs
|
|
totalCost := CalculateTeamCosts(composition, salaries)
|
|
|
|
return totalCost, composition
|
|
}
|
|
|
|
// GetYearlyTeamComposition returns team composition for a given year.
|
|
// This can be extended to read from params.yaml if team structure is defined there.
|
|
func GetYearlyTeamComposition(year int, p *params.Params) TeamComposition {
|
|
salaries := DefaultSalaries()
|
|
_, composition := CalculateTeamCostsFromParams(year, p, salaries)
|
|
|
|
// Adjust based on year (team grows over time)
|
|
if year >= 2 {
|
|
composition.CustomerSuccess = 1 // Add customer success in year 2+
|
|
}
|
|
if year >= 3 {
|
|
composition.Operations = 1 // Add operations in year 3+
|
|
}
|
|
|
|
return composition
|
|
}
|
|
|