271 lines
9.1 KiB
Go
271 lines
9.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"git.entr0py.de/garionion/berkutschi/client"
|
|
"git.entr0py.de/garionion/gstreamer-graphix/api"
|
|
"github.com/ilyakaznacheev/cleanenv"
|
|
jsoniter "github.com/json-iterator/go"
|
|
"github.com/rs/zerolog/pkgerrors"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"git.entr0py.de/garionion/berkutschi/berkutschi"
|
|
)
|
|
|
|
type Config struct {
|
|
GstServer string `yaml:"gstServer"`
|
|
ImagePath string `yaml:"imagePath" env-default:"./images"`
|
|
PositionsPath string `yaml:"positionsPath" env-default:"./positions.json"`
|
|
Event int `yaml:"event"`
|
|
LogFile string `yaml:"logFile"`
|
|
}
|
|
|
|
//TODO config struct thingy
|
|
var Judges = [5]JugdeRaceInfo{}
|
|
var PositionsConfig = Positions{}
|
|
var cfg Config
|
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
var apiClient *client.APIClient
|
|
|
|
func main() {
|
|
zerolog.TimeFieldFormat = time.RFC1123Z
|
|
consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC1123Z}
|
|
log.Logger = log.Output(consoleWriter).With().Timestamp().Caller().Logger()
|
|
|
|
if err := cleanenv.ReadConfig("config.toml", &cfg); err != nil {
|
|
log.Fatal().Msgf("No configfile: ", err)
|
|
}
|
|
|
|
fset := flag.NewFlagSet("config", flag.ContinueOnError)
|
|
fset.Usage = cleanenv.FUsage(fset.Output(), &cfg, nil, fset.Usage)
|
|
fset.Parse(os.Args[1:])
|
|
|
|
if cfg.LogFile != "" {
|
|
l, _ := os.OpenFile(cfg.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664)
|
|
multi := zerolog.MultiLevelWriter(consoleWriter, l)
|
|
log.Logger = zerolog.New(multi).With().Timestamp().Caller().Logger()
|
|
}
|
|
if log.Logger.GetLevel() == zerolog.DebugLevel {
|
|
zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
|
|
}
|
|
|
|
//TODO: error handling
|
|
jsonFile, err := os.Open(cfg.PositionsPath)
|
|
byteValue, _ := ioutil.ReadAll(jsonFile)
|
|
jsoniter.Unmarshal(byteValue, PositionsConfig)
|
|
|
|
apiClient = client.Init(cfg.GstServer)
|
|
|
|
pollData, err := berkutschi.Poll(cfg.Event)
|
|
if err != nil {
|
|
log.Panic().Err(fmt.Errorf("Error while polling: %s", err)).Send()
|
|
}
|
|
fillJudgeraceinfo(pollData)
|
|
|
|
ctx, _ := context.WithCancel(context.Background())
|
|
b := berkutschi.Init(cfg.Event, ctx)
|
|
|
|
go func() {
|
|
jumperInfoMap := make(map[string]string)
|
|
jumperScoreMap := make(map[string]string)
|
|
jumperInfo := JumperInfo{}
|
|
jumperScore := JumperScore{}
|
|
for {
|
|
message := <-b.RX
|
|
var jumpMessage BerkutschiJumpUpdateMessages
|
|
err := json.Unmarshal(message, &jumpMessage)
|
|
//log.Debug().Msgf("Received message: %v", string(message))
|
|
if err == nil && jumpMessage[0].Data.Current.Lastname != "" {
|
|
jumper, err := fillJumperInfo(jumpMessage)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if newJumperInfoData(jumperInfo, jumper) {
|
|
log.Info().Msgf("New jumper info: %+v", jumperInfo)
|
|
if jumper.Name == jumperInfo.Name {
|
|
overlays, _ := jumper.convertToAPIOverlays(PositionsConfig)
|
|
err = apiClient.UpdatePipeline(jumperInfoMap[jumper.Name], overlays)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("Error while updating jumperinfo of %s pipeline", jumper.Name)
|
|
}
|
|
} else {
|
|
id, err := jumper.createPipeline()
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("Error while creating jumperInfo pipeline for %s", jumper.Name)
|
|
}
|
|
log.Info().Msgf("Created jumperInfo pipeline for %s", jumper.Name)
|
|
jumperInfoMap[jumper.Name] = id
|
|
err = apiClient.DeletePipeline(jumperInfoMap[jumperInfo.Name])
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("Error while deleting pipeline of %s", jumperInfo.Name)
|
|
}
|
|
delete(jumperInfoMap, jumperInfo.Name)
|
|
}
|
|
jumperInfo = jumper
|
|
}
|
|
score, _ := fillJumperScore(jumpMessage)
|
|
if score.Rank != 0 && newJumperScoreData(jumperScore, score) {
|
|
log.Info().Msgf("New jumper score: %+v", jumperScore)
|
|
if jumperScore.Name == score.Name {
|
|
overlays, _ := score.convertToAPIOverlays(PositionsConfig)
|
|
err = apiClient.UpdatePipeline(jumperScoreMap[jumperScore.Name], overlays)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("Error while updating jumperScore of %s pipeline", jumperScore.Name)
|
|
}
|
|
} else {
|
|
id, err := score.createPipeline()
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("Error while creating jumperScore pipeline for %s", score.Name)
|
|
}
|
|
log.Info().Msgf("Created jumperScore pipeline for %s", score.Name)
|
|
jumperScoreMap[score.Name] = id
|
|
err = apiClient.DeletePipeline(jumperScoreMap[jumperScore.Name])
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("Error while deleting pipeline of %s", jumperScore.Name)
|
|
}
|
|
delete(jumperScoreMap, jumperScore.Name)
|
|
}
|
|
jumperScore = score
|
|
}
|
|
} else if err != nil {
|
|
log.Error().RawJSON("receivedMessage", message).Err(fmt.Errorf("%v", err))
|
|
} else {
|
|
if jumpMessage[0].Data.Next.Lastname == "" {
|
|
log.Debug().RawJSON("receivedMessage", message).Msg("Received message i cant decode")
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
<-ctx.Done()
|
|
}
|
|
|
|
func (d JumperInfo) createPipeline() (string, error) {
|
|
overlays, err := d.convertToAPIOverlays(PositionsConfig)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
pipeline := &api.Pipeline{
|
|
Name: "jumperinfo",
|
|
Clip: "CoC_20_Jumper_Infos_Fast.raw",
|
|
Output: "decklinkvideosink",
|
|
Overlays: overlays,
|
|
}
|
|
return apiClient.CreatePipeline(pipeline)
|
|
}
|
|
|
|
func (d JumperScore) createPipeline() (string, error) {
|
|
overlays, err := d.convertToAPIOverlays(PositionsConfig)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
pipeline := &api.Pipeline{
|
|
Name: "jumperscore",
|
|
Clip: "CoC_20_Jumper_Score_Fast.raw",
|
|
Output: "decklinkvideosink",
|
|
Overlays: overlays,
|
|
}
|
|
return apiClient.CreatePipeline(pipeline)
|
|
}
|
|
|
|
func fillJumperInfo(m BerkutschiJumpUpdateMessages) (JumperInfo, error) {
|
|
var err error
|
|
JumperInfo := JumperInfo{}
|
|
if m[0].Data.Current.Firstname == "" || m[0].Data.Current.Lastname == "" {
|
|
err = fmt.Errorf("Name is empty")
|
|
return JumperInfo, err
|
|
}
|
|
JumperInfo.Name = fmt.Sprint(m[0].Data.Current.Firstname, " ", strings.ToUpper(m[0].Data.Current.Lastname))
|
|
JumperInfo.Bib = m[0].Data.Current.Bib
|
|
JumperInfo.Nation = strings.ToUpper(m[0].Data.Current.Nat)
|
|
JumperInfo.Image = m[0].Data.Current.Image2
|
|
|
|
return JumperInfo, err
|
|
}
|
|
|
|
func fillJumperScore(m BerkutschiJumpUpdateMessages) (JumperScore, error) {
|
|
var err error
|
|
JumperScore := JumperScore{}
|
|
if m[0].Data.Current.Firstname == "" || m[0].Data.Current.Lastname == "" {
|
|
err = fmt.Errorf("Name is empty")
|
|
return JumperScore, err
|
|
}
|
|
JumperScore.Name = fmt.Sprint(m[0].Data.Current.Firstname, " ", strings.ToUpper(m[0].Data.Current.Lastname))
|
|
JumperScore.Bib = m[0].Data.Current.Bib
|
|
JumperScore.Nation = strings.ToUpper(m[0].Data.Current.Nat)
|
|
JumperScore.Points = m[0].Data.Current.Cumul.Points
|
|
JumperScore.Rank = m[0].Data.Current.Cumul.Rank
|
|
JumperScore.Wind = m[0].Data.Current.Wind.Wind
|
|
JumperScore.Length = fmt.Sprintf("%vm", m[0].Data.Current.Length.Length)
|
|
for i := range JumperScore.Judges {
|
|
switch i {
|
|
case 0:
|
|
JumperScore.Judges[i].Score = m[0].Data.Current.Judge.One.Rate
|
|
JumperScore.Judges[i].Nation = Judges[i].Nation
|
|
JumperScore.Judges[i].Discard = m[0].Data.Current.Judge.One.Discard
|
|
case 1:
|
|
JumperScore.Judges[i].Score = m[0].Data.Current.Judge.Two.Rate
|
|
JumperScore.Judges[i].Nation = Judges[i].Nation
|
|
JumperScore.Judges[i].Discard = m[0].Data.Current.Judge.Two.Discard
|
|
case 2:
|
|
JumperScore.Judges[i].Score = m[0].Data.Current.Judge.Three.Rate
|
|
JumperScore.Judges[i].Nation = Judges[i].Nation
|
|
JumperScore.Judges[i].Discard = m[0].Data.Current.Judge.Three.Discard
|
|
case 3:
|
|
JumperScore.Judges[i].Score = m[0].Data.Current.Judge.Four.Rate
|
|
JumperScore.Judges[i].Nation = Judges[i].Nation
|
|
JumperScore.Judges[i].Discard = m[0].Data.Current.Judge.Four.Discard
|
|
case 4:
|
|
JumperScore.Judges[i].Score = m[0].Data.Current.Judge.Five.Rate
|
|
JumperScore.Judges[i].Nation = Judges[i].Nation
|
|
JumperScore.Judges[i].Discard = m[0].Data.Current.Judge.Five.Discard
|
|
}
|
|
}
|
|
|
|
return JumperScore, err
|
|
}
|
|
|
|
func fillJudgeraceinfo(data berkutschi.PollData) {
|
|
for i := range Judges {
|
|
switch i {
|
|
case 0:
|
|
Judges[i].Nation = strings.ToUpper(data.Data.Raceinfo.Judges.One.Nation)
|
|
case 1:
|
|
Judges[i].Nation = strings.ToUpper(data.Data.Raceinfo.Judges.Two.Nation)
|
|
case 2:
|
|
Judges[i].Nation = strings.ToUpper(data.Data.Raceinfo.Judges.Three.Nation)
|
|
case 3:
|
|
Judges[i].Nation = strings.ToUpper(data.Data.Raceinfo.Judges.Four.Nation)
|
|
case 4:
|
|
Judges[i].Nation = strings.ToUpper(data.Data.Raceinfo.Judges.Five.Nation)
|
|
}
|
|
}
|
|
}
|
|
|
|
func newJumperInfoData(oldData, newData JumperInfo) bool {
|
|
if oldData.Name != newData.Name || oldData.Bib != newData.Bib || oldData.Nation != newData.Nation || oldData.Image != newData.Image {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
func newJumperScoreData(oldData, newData JumperScore) bool {
|
|
if oldData.Name != newData.Name || oldData.Bib != newData.Bib || oldData.Nation != newData.Nation ||
|
|
oldData.Points != newData.Points || oldData.Rank != newData.Rank || oldData.Wind != newData.Wind || oldData.Length != newData.Length {
|
|
return true
|
|
}
|
|
for i, oldJudge := range oldData.Judges {
|
|
if oldJudge.Score != newData.Judges[i].Score || oldJudge.Nation != newData.Judges[i].Nation || oldJudge.Discard != newData.Judges[i].Discard {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|