Files
goodcalc/matrix.go
2021-01-03 08:08:10 +01:00

119 lines
3.5 KiB
Go

package goodcalc
import (
"fmt"
"math"
)
// 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"`
}
func (m *Matrix) String() string {
if m == nil {
return "<nil>"
}
var s string
s += fmt.Sprintf("MaxPoints: %d\n", m.MaxPoints)
s += fmt.Sprintf("MaxValuationPoints: %d\n", m.MaxValuationPoints)
s += fmt.Sprintf("MaxNegValuationPoints: %d\n", m.MaxNegValuationPoints)
s += fmt.Sprintf("NegPointsFactor: %d\n", m.NegPointsFactor)
s += fmt.Sprintf("Calculation: %#v\n", m.Calculation)
s += fmt.Sprintf("Stakeholders: {\n%s\n}\n", m.Stakeholders)
return s
}
// BalancePoints calculates the ecogood points for the matrix
func (m *Matrix) BalancePoints() int {
var balancePoints float64
m.calcWeightFactor()
m.setMaxValuationPoints()
m.forall(func(t *Theme) {
t.Calc.calcMaxPoints()
t.calcNrPosAspects()
t.calcValPoints()
t.calcEstPercentage()
t.calcBalancePoints()
balancePoints += float64(t.Calc.BalancePoints)
balancePoints += float64(t.Calc.NegativeBlancePoints)
})
balancePoints = math.Round(balancePoints)
return int(balancePoints)
}
// 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)
}
}
}
// sumCalcWeight sums all the calculated weights of
// the matrix.
func (m *Matrix) sumCalcWeight() {
// calculate the stakeholder weight to each
// theme
for _, s := range m.Stakeholders {
s.calcWeight()
}
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.MaxValuationPoints * int(a.Weight)
}
t.Calc.MaxValuationPoints = maxThemeValPoints
for _, na := range t.NegativeAspects {
na.maxValuationPoints = m.MaxNegValuationPoints
}
t.negPointsFactor = m.NegPointsFactor
})
}