From d646a0d6107e49310e6983856c39ad66b92d4154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Schr=C3=B6pfer?= Date: Wed, 23 Dec 2020 21:27:12 +0100 Subject: [PATCH] first calculation logic --- .gitignore | 1 + MatrixBerechnung.ods | Bin 16164 -> 16283 bytes goodcalc.go | 57 +++------------------------------ matrix.go | 74 +++++++++++++++++++++++++++++++++++++++++++ stakeholder.go | 17 ++++++++++ theme.go | 64 +++++++++++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 53 deletions(-) create mode 100644 matrix.go create mode 100644 stakeholder.go create mode 100644 theme.go 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 fbbf201209060bff58579913b3f9de9485950bd9..f212f511372523049a6c71d1418e1f447ed0e8e8 100644 GIT binary patch delta 13720 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 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 +}