diff --git a/.gitignore b/.gitignore index f4d432a..426169a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ # Dependency directories (remove the comment below to include it) # vendor/ +.~lock.*.ods# diff --git a/MatrixBerechnung.ods b/MatrixBerechnung.ods index fbbf201..f212f51 100644 Binary files a/MatrixBerechnung.ods and b/MatrixBerechnung.ods differ diff --git a/goodcalc.go b/goodcalc.go index 4c53256..83b6fe2 100644 --- a/goodcalc.go +++ b/goodcalc.go @@ -5,47 +5,12 @@ // repository. package goodcalc -// Matrix contains the stakeholders and the maximal -// allowed points of the calculation. The calculation -// is pretty simple. Inside each aspect ValuationPoints -// can be defined. Over the maximal possible points -// the balancePoints are calculated. -// -// It is possible to define different weights on different -// layers (stakeholder, theme and aspect). -// This type does not contain any businesslogic of the version -// of the matrix. -type Matrix struct { - MaxPoints int `json:"max_points,omitempty"` - Stakeholders []Stakeholder `json:"stakeholders,omitempty"` -} - -// Stakeholder can define a weight, which is calculated to -// all containing themes. -// No is the id like in the excel -// For example A for Suppliers -type Stakeholder struct { - No string `json:"no,omitempty"` - Weight float32 `json:"weight,omitempty"` - Themes []Theme `json:"themes,omitempty"` -} - -// Theme is the basic element of the matrix. -// No defines the id of the excel balance. -// A1 for Human dignity in the supply chain -type Theme struct { - No string `json:"no,omitempty"` - Weight float32 `json:"weight,omitempty"` - Aspects []Aspect `json:"aspects,omitempty"` - NegativeAspects []NegativeAspect `json:"negative_aspects,omitempty"` - Calculation ThemeCalc `json:"calculation,omitempty"` -} - // Aspect does contain the valuation of the company. type Aspect struct { - No string `json:"no,omitempty"` - Weight float32 `json:"weight,omitempty"` - ValuationPoints int `json:"valuation_points,omitempty"` + No string `json:"no"` + Weight float32 `json:"weight"` + MaxValuationPoints int `json:"max_valuation_points"` + ValuationPoints int `json:"valuation_points"` } // NegativeAspect has the same fields like Aspect. But the @@ -53,17 +18,3 @@ type Aspect struct { type NegativeAspect struct { Aspect } - -// ThemeCalc contains the different calculation -// steps. -type ThemeCalc struct { - CalcWeight float32 `json:"calc_weight,omitempty"` - WeightFactor float32 `json:"weight_factor,omitempty"` - MaxPoints float32 `json:"max_points,omitempty"` - NrPositiveAspects int `json:"nr_positive_aspects,omitempty"` - ValuationPoints int `json:"valuation_points,omitempty"` - EstPercentage float32 `json:"est_percentage,omitempty"` - BalancePoints int `json:"balance_points,omitempty"` - NegativeValuationPoints int `json:"negative_valuation_points,omitempty"` - NegativeBlancePoints int `json:"negative_blance_points,omitempty"` -} diff --git a/matrix.go b/matrix.go new file mode 100644 index 0000000..2982b0d --- /dev/null +++ b/matrix.go @@ -0,0 +1,74 @@ +package goodcalc + +// Matrix contains the stakeholders and the maximal +// allowed points of the calculation. The calculation +// is pretty simple. Inside each aspect ValuationPoints +// can be defined. Over the maximal possible points +// the balancePoints are calculated. +// +// It is possible to define different weights on different +// layers (stakeholder, theme and aspect). +// This type does not contain any businesslogic of the version +// of the matrix. +type Matrix struct { + MaxPoints int `json:"max_points"` + MaxValuationPoints int `json:"max_valuation_points"` // 10 + MaxNegValuationPoints int `json:"max_neg_valuation_points"` // -200 + NegPointsFactor int `json:"neg_points_factor"` // 50 + Stakeholders []*Stakeholder `json:"stakeholders"` + Calculation MatrixCalc `json:"calculation"` +} + +// MatrixCalc contains calculated values +type MatrixCalc struct { + SumCalcWeight float32 `json:"sum_calc_weight"` + WeightFactor float32 `json:"weight_factor"` +} + +// forall is a helper-method for iterating the themes +func (m *Matrix) forall(f func(t *Theme)) { + for _, s := range m.Stakeholders { + for _, t := range s.Themes { + f(t) + } + } +} + +func (m *Matrix) sumCalcWeight() { + m.Calculation.SumCalcWeight = 0 + m.forall(func(t *Theme) { + m.Calculation.SumCalcWeight += t.Calc.CalcWeight + }) + +} + +func (m *Matrix) calcWeightFactor() { + m.sumCalcWeight() + m.Calculation.WeightFactor = 0 + if m.Calculation.SumCalcWeight != 0 { + m.Calculation.WeightFactor = float32(m.MaxPoints) / m.Calculation.SumCalcWeight + } + // set the weight-factor for all elements of the matrix + // this redundancy enables the calculation on the theme + // without reading from the matrix + m.forall(func(t *Theme) { + t.Calc.WeightFactor = m.Calculation.WeightFactor + }) +} + +// setMaxValuationPoints writes the config values of the matrix into the themes and +// aspects +func (m *Matrix) setMaxValuationPoints() { + m.forall(func(t *Theme) { + maxThemeValPoints := 0 + for _, a := range t.Aspects { + a.MaxValuationPoints = m.MaxValuationPoints * int(a.Weight) + maxThemeValPoints += m.MaxNegValuationPoints * int(a.Weight) + } + t.Calc.MaxValuationPoints = maxThemeValPoints + for _, na := range t.NegativeAspects { + na.MaxValuationPoints = m.MaxNegValuationPoints + } + t.NegPointsFactor = m.NegPointsFactor + }) +} diff --git a/stakeholder.go b/stakeholder.go new file mode 100644 index 0000000..3b766b8 --- /dev/null +++ b/stakeholder.go @@ -0,0 +1,17 @@ +package goodcalc + +// Stakeholder can define a weight, which is calculated to +// all containing themes. +// No is the id like in the excel +// For example A for Suppliers +type Stakeholder struct { + No string `json:"no"` + Weight float32 `json:"weight"` + Themes []*Theme `json:"themes"` +} + +func (s *Stakeholder) calcWeight() { + for _, t := range s.Themes { + t.Calc.CalcWeight = s.Weight * t.Weight + } +} diff --git a/theme.go b/theme.go new file mode 100644 index 0000000..73ba742 --- /dev/null +++ b/theme.go @@ -0,0 +1,64 @@ +package goodcalc + +// Theme is the basic element of the matrix. +// No defines the id of the excel balance. +// A1 for Human dignity in the supply chain +type Theme struct { + No string `json:"no"` + Weight float32 `json:"weight"` + Aspects []Aspect `json:"aspects"` + NegativeAspects []NegativeAspect `json:"negative_aspects"` + NegPointsFactor int `json:"neg_points_factor"` + Calc *ThemeCalc `json:"calculation"` +} + +func (t *Theme) calcNrPosAspects() { + t.Calc.NrPositiveAspects = len(t.Aspects) +} + +func (t *Theme) calcValPoints() { + t.Calc.ValuationPoints = 0 + for _, a := range t.Aspects { + t.Calc.ValuationPoints += a.ValuationPoints * int(a.Weight) + } + for _, na := range t.NegativeAspects { + t.Calc.NegativeValuationPoints += + na.ValuationPoints * int(na.Weight) + } +} + +func (t *Theme) calcEstPercentage() { + t.Calc.EstPercentage = 0 + if t.Calc.MaxValuationPoints != 0 { + t.Calc.EstPercentage = + float32(t.Calc.ValuationPoints / t.Calc.MaxValuationPoints) + } +} + +func (t *Theme) calcBalancePoints() { + t.Calc.BalancePoints = + t.Calc.EstPercentage * t.Calc.MaxBalancePoints + t.Calc.NegativeBlancePoints = + float32(t.Calc.NegativeValuationPoints) * t.Calc.MaxBalancePoints / float32(t.NegPointsFactor) +} + +// ThemeCalc contains the different calculation +// steps. +type ThemeCalc struct { + CalcWeight float32 `json:"calc_weight"` + WeightFactor float32 `json:"weight_factor"` + MaxBalancePoints float32 `json:"max_points"` + NrPositiveAspects int `json:"nr_positive_aspects"` + ValuationPoints int `json:"valuation_points"` + MaxValuationPoints int `json:"max_valuation_points"` + EstPercentage float32 `json:"est_percentage"` + BalancePoints float32 `json:"balance_points"` + NegativeValuationPoints int `json:"negative_valuation_points"` + NegativeBlancePoints float32 `json:"negative_blance_points"` +} + +// calcMaxPoints +// Stakeholder.calcWeight needs to run first +func (c *ThemeCalc) calcMaxPoints() { + c.MaxBalancePoints = c.CalcWeight * c.WeightFactor +}