api/app/trading.go

103 lines
2.2 KiB
Go

package app
import (
"fmt"
"math"
"git.fuyu.moe/5GPowerQuality/api/app/internal/model"
"git.ultraware.nl/NiseVoid/qb"
"git.ultraware.nl/NiseVoid/qb/qc"
)
// GetScores returns the scores for the trading page
func GetScores(meterID int) []Scores {
m := model.Measurement()
q := m.Select(
m.UGem1, m.UGem2, m.UGem3,
m.IMax1, m.IMax2, m.IMax3,
m.CGem1, m.CGem2, m.CGem3,
).
Where(qc.Eq(m.MeterID, meterID)).
OrderBy(qb.Desc(m.Time))
data := [3]powerData{}
err := db.QueryRow(q).Scan(
&data[0].Voltage, &data[1].Voltage, &data[2].Voltage,
&data[0].MaxAmpere, &data[1].MaxAmpere, &data[2].MaxAmpere,
&data[0].CosPhi, &data[1].CosPhi, &data[2].CosPhi,
)
if err != nil {
panic(err)
}
scores := make([]Scores, 3)
for k, v := range data {
scores[k] = Scores{
Phase: k + 1,
Producation: productionScore(v),
Usage: usageScore(v),
Storage: storageScore(v),
}
}
return scores
}
// Scores contains all scores for a phase
type Scores struct {
Phase int `json:"phase"`
Producation float64 `json:"production"`
Usage float64 `json:"usage"`
Storage float64 `json:"storage"`
}
type powerData struct {
Voltage float64
MaxAmpere float64
CosPhi float64
}
func (data powerData) String() string {
return fmt.Sprintf(`%3.0fV, %3.0fA, %.1fφ`, data.Voltage, data.MaxAmpere, data.CosPhi)
}
func getScoreModifier(expected, value, step float64) float64 {
var neg bool
if value-expected < 0 {
neg = true
}
r := math.Pow((value-expected)/step, 2)
if neg {
r = r * -1
}
return r
}
func productionScore(data powerData) float64 {
vMod := getScoreModifier(230, data.Voltage, 5) * -1
aMod := getScoreModifier(100, data.MaxAmpere, 25) * -1
if aMod > 0 {
aMod = 0
}
cpMod := getScoreModifier(0.8, math.Abs(data.CosPhi), 0.1)
return vMod + aMod + cpMod
}
func usageScore(data powerData) float64 {
vMod := getScoreModifier(230, data.Voltage, 5)
aMod := getScoreModifier(100, data.MaxAmpere, 25) * -1
if aMod > 0 {
aMod = 0
}
return vMod + aMod
}
func storageScore(data powerData) float64 {
vMod := getScoreModifier(230, data.Voltage, 5)
cpMod := getScoreModifier(0.8, math.Abs(data.CosPhi), 0.1) * -1
return vMod + cpMod
}