first calculation logic

This commit is contained in:
Andreas Schröpfer
2020-12-23 21:27:12 +01:00
parent 6995f73627
commit d646a0d610
6 changed files with 160 additions and 53 deletions

1
.gitignore vendored
View File

@@ -15,3 +15,4 @@
# Dependency directories (remove the comment below to include it)
# vendor/
.~lock.*.ods#

Binary file not shown.

View File

@@ -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"`
}

74
matrix.go Normal file
View File

@@ -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
})
}

17
stakeholder.go Normal file
View File

@@ -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
}
}

64
theme.go Normal file
View File

@@ -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
}