This commit is contained in:
Linrador 2025-06-11 06:15:57 +02:00
parent 85d13c60fd
commit b316d1f7a6
3 changed files with 114 additions and 15 deletions

107
main.go
View File

@ -5,6 +5,7 @@ import (
"fmt"
"math"
"os"
"time"
demoinfocs "github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs"
"github.com/markus-wa/demoinfocs-golang/v4/pkg/demoinfocs/common"
@ -30,18 +31,32 @@ type PlayerStats struct {
Headshots int `json:"headshots"`
NoScopes int `json:"noScopes"`
BlindKills int `json:"blindKills"`
RankOld int `json:"rankOld,omitempty"`
RankNew int `json:"rankNew,omitempty"`
RankChange int `json:"rankChange,omitempty"`
WinCount int `json:"winCount,omitempty"`
}
type RoundResult struct {
Round int `json:"round"`
Winner string `json:"winner"`
WinReason string `json:"winReason"`
}
type DemoMeta struct {
MatchID uint64 `json:"matchId"`
Map string `json:"map"`
Players []PlayerStats `json:"players"`
Duration float64 `json:"duration"`
TickRate float64 `json:"tickRate"`
ScoreCT int `json:"scoreCT"`
ScoreT int `json:"scoreT"`
TeamCT string `json:"teamCT"`
TeamT string `json:"teamT"`
WinnerTeam string `json:"winnerTeam"`
RoundCount int `json:"roundCount"`
RoundHistory []RoundResult `json:"roundHistory"`
DemoDate string `json:"demoDate"`
}
func sanitizeFloat(value float64) float64 {
@ -51,6 +66,43 @@ func sanitizeFloat(value float64) float64 {
return value
}
func getDemoTimestamp(path string) string {
info, err := os.Stat(path)
if err != nil {
return ""
}
return info.ModTime().UTC().Format("2006-01-02T15:04:05Z")
}
func reasonToString(reason events.RoundEndReason) string {
switch reason {
case events.RoundEndReasonTargetBombed:
return "Bomb"
case events.RoundEndReasonTerroristsStopped:
return "T eliminated"
case events.RoundEndReasonCTStoppedEscape:
return "CT stopped escape"
case events.RoundEndReasonTerroristsEscaped:
return "T escaped"
case events.RoundEndReasonHostagesRescued:
return "Hostages rescued"
case events.RoundEndReasonCTWin:
return "CT win"
case events.RoundEndReasonTerroristsWin:
return "T win"
case events.RoundEndReasonDraw:
return "Draw"
case events.RoundEndReasonHostagesNotRescued:
return "Hostages not rescued"
case events.RoundEndReasonTerroristsNotEscaped:
return "T not escaped"
case events.RoundEndReasonBombDefused:
return "Bomb defused"
default:
return "Unknown"
}
}
func main() {
if len(os.Args) < 2 {
fmt.Println("❌ Demo-Datei fehlt")
@ -69,6 +121,8 @@ func main() {
var mapName string
var matchId uint64
var scoreCT, scoreT, roundCount int
var roundHistory []RoundResult
if len(os.Args) >= 3 {
inputId := os.Args[2]
@ -79,7 +133,6 @@ func main() {
}
}
// Hole Mapname aus ServerInfo (zuverlässiger als Header.MapName)
p.RegisterNetMessageHandler(func(msg *msg.CSVCMsg_ServerInfo) {
if msg != nil && msg.GetMapName() != "" {
mapName = msg.GetMapName()
@ -166,12 +219,34 @@ func main() {
}
})
// 📊 Premier Rank / Elo Veränderung
p.RegisterEventHandler(func(e events.RoundEnd) {
scoreCT = p.GameState().TeamCounterTerrorists().Score()
scoreT = p.GameState().TeamTerrorists().Score()
roundCount++
var winner string
switch e.Winner {
case common.TeamTerrorists:
winner = "T"
case common.TeamCounterTerrorists:
winner = "CT"
default:
winner = "Unknown"
}
roundHistory = append(roundHistory, RoundResult{
Round: roundCount,
Winner: winner,
WinReason: reasonToString(e.Reason),
})
})
p.RegisterEventHandler(func(e events.RankUpdate) {
if e.Player != nil {
stat := getOrCreate(e.Player.SteamID64, e.Player.Name)
stat.RankOld = e.RankOld
stat.RankNew = e.RankNew
stat.RankChange = int(e.RankChange)
stat.WinCount = e.WinCount
}
})
@ -182,13 +257,29 @@ func main() {
os.Exit(1)
}
teamCT := p.GameState().TeamCounterTerrorists().ClanName()
teamT := p.GameState().TeamTerrorists().ClanName()
scoreCT = p.GameState().TeamCounterTerrorists().Score()
scoreT = p.GameState().TeamTerrorists().Score()
winnerTeam := "Draw"
if scoreCT > scoreT {
winnerTeam = teamCT
} else if scoreT > scoreCT {
winnerTeam = teamT
}
demoDate := getDemoTimestamp(filePath)
if demoDate == "" {
demoDate = time.Now().UTC().Format("2006-01-02T15:04:05Z")
}
duration := sanitizeFloat(header.PlaybackTime.Seconds())
tickRate := 0.0
if duration > 0 {
tickRate = sanitizeFloat(float64(header.PlaybackTicks) / duration)
}
// Fallback auf Header-Map, falls kein ServerInfo-Mapname verfügbar
if mapName == "" {
mapName = header.MapName
}
@ -198,6 +289,14 @@ func main() {
Map: mapName,
Duration: duration,
TickRate: tickRate,
ScoreCT: scoreCT,
ScoreT: scoreT,
TeamCT: teamCT,
TeamT: teamT,
WinnerTeam: winnerTeam,
RoundCount: roundCount,
RoundHistory: roundHistory,
DemoDate: demoDate,
}
for _, stat := range playerStats {

Binary file not shown.

Binary file not shown.