added detailed parsing of player hurt events
This commit is contained in:
180
main.go
180
main.go
@@ -9,6 +9,7 @@ import (
|
||||
"csgowtfd/ent/player"
|
||||
"csgowtfd/ent/stats"
|
||||
"csgowtfd/utils"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/go-redis/cache/v8"
|
||||
@@ -49,6 +50,7 @@ type PlayerResponse struct {
|
||||
Name string `json:"name"`
|
||||
Avatar string `json:"avatar"`
|
||||
VAC bool `json:"vac"`
|
||||
VACDate time.Time `json:"vac_date,omitempty"`
|
||||
Tracked bool `json:"tracked"`
|
||||
VanityURL string `json:"vanity_url,omitempty"`
|
||||
MatchStats utils.MatchStats `json:"match_stats,omitempty"`
|
||||
@@ -56,28 +58,73 @@ type PlayerResponse struct {
|
||||
}
|
||||
|
||||
type MatchResponse struct {
|
||||
MatchId uint64 `json:"match_id,string"`
|
||||
ShareCode string `json:"share_code"`
|
||||
Map string `json:"map"`
|
||||
Date time.Time `json:"date"`
|
||||
Score [2]int `json:"score"`
|
||||
Duration int `json:"duration"`
|
||||
MatchResult int `json:"match_result"`
|
||||
MaxRounds int `json:"max_rounds,omitempty"`
|
||||
Parsed bool `json:"parsed"`
|
||||
Stats []*StatsResponse `json:"stats"`
|
||||
MatchId uint64 `json:"match_id,string"`
|
||||
ShareCode string `json:"share_code,omitempty"`
|
||||
Map string `json:"map"`
|
||||
Date time.Time `json:"date"`
|
||||
Score [2]int `json:"score"`
|
||||
Duration int `json:"duration"`
|
||||
MatchResult int `json:"match_result"`
|
||||
MaxRounds int `json:"max_rounds,omitempty"`
|
||||
Parsed bool `json:"parsed"`
|
||||
Stats interface{} `json:"stats,omitempty"`
|
||||
}
|
||||
|
||||
type StatsResponse struct {
|
||||
TeamID int `json:"team_id"`
|
||||
Kills int `json:"kills"`
|
||||
Deaths int `json:"deaths"`
|
||||
Assists int `json:"assists"`
|
||||
Headshot int `json:"headshot"`
|
||||
MVP int `json:"mvp"`
|
||||
Score int `json:"score"`
|
||||
Player PlayerResponse `json:"player"`
|
||||
Extended interface{} `json:"extended,omitempty"`
|
||||
TeamID int `json:"team_id"`
|
||||
Kills int `json:"kills"`
|
||||
Deaths int `json:"deaths"`
|
||||
Assists int `json:"assists"`
|
||||
Headshot int `json:"headshot"`
|
||||
MVP uint `json:"mvp"`
|
||||
Score int `json:"score"`
|
||||
Player interface{} `json:"player,omitempty"`
|
||||
Rank struct {
|
||||
Old int `json:"old,omitempty"`
|
||||
New int `json:"new,omitempty"`
|
||||
} `json:"rank,omitempty"`
|
||||
MultiKills struct {
|
||||
Duo uint `json:"duo,omitempty"`
|
||||
Triple uint `json:"triple,omitempty"`
|
||||
Quad uint `json:"quad,omitempty"`
|
||||
Pent uint `json:"pent,omitempty"`
|
||||
} `json:"multi_kills,omitempty"`
|
||||
Dmg struct {
|
||||
Enemy uint `json:"enemy,omitempty"`
|
||||
Team uint `json:"team,omitempty"`
|
||||
UD struct {
|
||||
HE uint `json:"he,omitempty"`
|
||||
Flames uint `json:"flames,omitempty"`
|
||||
Flash uint `json:"flash,omitempty"`
|
||||
Decoy uint `json:"decoy,omitempty"`
|
||||
Smoke uint `json:"smoke,omitempty"`
|
||||
} `json:"ud,omitempty"`
|
||||
HitGroup struct {
|
||||
Head uint `json:"head,omitempty"`
|
||||
Chest uint `json:"chest,omitempty"`
|
||||
Stomach uint `json:"stomach,omitempty"`
|
||||
LeftArm uint `json:"left_arm,omitempty"`
|
||||
RightArm uint `json:"right_arm,omitempty"`
|
||||
LeftLeg uint `json:"left_leg,omitempty"`
|
||||
RightLeg uint `json:"right_leg,omitempty"`
|
||||
Gear uint `json:"gear,omitempty"`
|
||||
} `json:"hit_group,omitempty"`
|
||||
} `json:"dmg,omitempty"`
|
||||
Flash struct {
|
||||
Duration struct {
|
||||
Self float32 `json:"self,omitempty"`
|
||||
Team float32 `json:"team,omitempty"`
|
||||
Enemy float32 `json:"enemy,omitempty"`
|
||||
} `json:"duration,omitempty"`
|
||||
Total struct {
|
||||
Team uint `json:"team,omitempty"`
|
||||
Enemy uint `json:"enemy,omitempty"`
|
||||
Self uint `json:"self,omitempty"`
|
||||
} `json:"total,omitempty"`
|
||||
} `json:"extended,omitempty"`
|
||||
Crosshair string `json:"crosshair,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
KAST int `json:"kast,omitempty"`
|
||||
}
|
||||
|
||||
func housekeeping() {
|
||||
@@ -174,13 +221,14 @@ func getPlayer(w http.ResponseWriter, r *http.Request) {
|
||||
Name: tPlayer.Name,
|
||||
Avatar: tPlayer.AvatarURL,
|
||||
VAC: tPlayer.Vac,
|
||||
VACDate: tPlayer.VacDate,
|
||||
VanityURL: tPlayer.VanityURLReal,
|
||||
Tracked: tPlayer.AuthCode != "",
|
||||
Matches: []*MatchResponse{},
|
||||
}
|
||||
|
||||
db.Lock.RLock()
|
||||
tMatches, err := tPlayer.QueryMatches().Order(ent.Desc(match.FieldDate)).Limit(20).All(context.Background())
|
||||
tMatches, err := tPlayer.QueryMatches().Order(ent.Desc(match.FieldDate)).Limit(10).All(context.Background())
|
||||
db.Lock.RUnlock()
|
||||
if err != nil {
|
||||
log.Debugf("[GP] No matches found for player %s", id)
|
||||
@@ -228,7 +276,6 @@ func getPlayer(w http.ResponseWriter, r *http.Request) {
|
||||
for _, iMatch := range tMatches {
|
||||
mResponse := &MatchResponse{
|
||||
MatchId: iMatch.ID,
|
||||
ShareCode: iMatch.ShareCode,
|
||||
Map: iMatch.Map,
|
||||
Date: iMatch.Date,
|
||||
Score: [2]int{iMatch.ScoreTeamA, iMatch.ScoreTeamB},
|
||||
@@ -236,31 +283,40 @@ func getPlayer(w http.ResponseWriter, r *http.Request) {
|
||||
MatchResult: iMatch.MatchResult,
|
||||
MaxRounds: iMatch.MaxRounds,
|
||||
Parsed: iMatch.DemoParsed,
|
||||
Stats: []*StatsResponse{},
|
||||
}
|
||||
|
||||
db.Lock.RLock()
|
||||
tStats, err := iMatch.QueryStats().Where(stats.HasPlayersWith(player.ID(tPlayer.ID))).WithPlayers().All(context.Background())
|
||||
tStats, err := iMatch.QueryStats().Modify(func(s *sql.Selector) {
|
||||
s.Select(stats.FieldTeamID, stats.FieldKills, stats.FieldDeaths, stats.FieldAssists, stats.FieldHeadshot,
|
||||
stats.FieldMvp, stats.FieldScore, stats.FieldMk2, stats.FieldMk3, stats.FieldMk4, stats.FieldMk5,
|
||||
stats.FieldRankOld, stats.FieldRankNew)
|
||||
s.Where(sql.EQ(s.C(stats.PlayersColumn), tPlayer.ID))
|
||||
}).Only(context.Background())
|
||||
db.Lock.RUnlock()
|
||||
if err != nil {
|
||||
response.Matches = append(response.Matches, mResponse)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, iStats := range tStats {
|
||||
sResponse := &StatsResponse{
|
||||
TeamID: iStats.TeamID,
|
||||
Kills: iStats.Kills,
|
||||
Deaths: iStats.Deaths,
|
||||
Assists: iStats.Assists,
|
||||
Headshot: iStats.Headshot,
|
||||
MVP: iStats.Mvp,
|
||||
Score: iStats.Score,
|
||||
Extended: iStats.Extended,
|
||||
}
|
||||
|
||||
mResponse.Stats = append(mResponse.Stats, sResponse)
|
||||
sResponse := &StatsResponse{
|
||||
TeamID: tStats.TeamID,
|
||||
Kills: tStats.Kills,
|
||||
Deaths: tStats.Deaths,
|
||||
Assists: tStats.Assists,
|
||||
Headshot: tStats.Headshot,
|
||||
MVP: tStats.Mvp,
|
||||
Score: tStats.Score,
|
||||
}
|
||||
|
||||
sResponse.MultiKills.Duo = tStats.Mk2
|
||||
sResponse.MultiKills.Triple = tStats.Mk3
|
||||
sResponse.MultiKills.Quad = tStats.Mk4
|
||||
sResponse.MultiKills.Pent = tStats.Mk5
|
||||
|
||||
sResponse.Rank.Old = tStats.RankOld
|
||||
sResponse.Rank.New = tStats.RankNew
|
||||
|
||||
mResponse.Stats = sResponse
|
||||
response.Matches = append(response.Matches, mResponse)
|
||||
}
|
||||
|
||||
@@ -322,7 +378,7 @@ func postPlayerTrackMe(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func getMatchParse(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -344,7 +400,7 @@ func getMatchParse(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
}
|
||||
|
||||
func getMatch(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -394,6 +450,8 @@ func getMatch(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
tmpStats := make([]*StatsResponse, 0)
|
||||
|
||||
for _, iStats := range tStats {
|
||||
sResponse := &StatsResponse{
|
||||
Player: PlayerResponse{
|
||||
@@ -411,11 +469,45 @@ func getMatch(w http.ResponseWriter, r *http.Request) {
|
||||
Headshot: iStats.Headshot,
|
||||
MVP: iStats.Mvp,
|
||||
Score: iStats.Score,
|
||||
Extended: iStats.Extended,
|
||||
}
|
||||
|
||||
mResponse.Stats = append(mResponse.Stats, sResponse)
|
||||
sResponse.Color = iStats.Color.String()
|
||||
sResponse.Crosshair = iStats.Crosshair
|
||||
sResponse.KAST = iStats.Kast
|
||||
sResponse.Dmg.Team = iStats.DmgTeam
|
||||
sResponse.Dmg.Enemy = iStats.DmgEnemy
|
||||
sResponse.Dmg.UD.HE = iStats.UdHe
|
||||
sResponse.Dmg.UD.Smoke = iStats.UdSmoke
|
||||
sResponse.Dmg.UD.Flash = iStats.UdFlash
|
||||
sResponse.Dmg.UD.Decoy = iStats.UdDecoy
|
||||
sResponse.Dmg.UD.Flames = iStats.UdFlames
|
||||
sResponse.Dmg.HitGroup.Gear = iStats.HitGroupGear
|
||||
sResponse.Dmg.HitGroup.LeftLeg = iStats.HitGroupLeftLeg
|
||||
sResponse.Dmg.HitGroup.RightLeg = iStats.HitGroupRightLeg
|
||||
sResponse.Dmg.HitGroup.RightArm = iStats.HitGroupRightArm
|
||||
sResponse.Dmg.HitGroup.LeftArm = iStats.HitGroupLeftArm
|
||||
sResponse.Dmg.HitGroup.Stomach = iStats.HitGroupStomach
|
||||
sResponse.Dmg.HitGroup.Chest = iStats.HitGroupChest
|
||||
sResponse.Dmg.HitGroup.Head = iStats.HitGroupHead
|
||||
sResponse.Rank.Old = iStats.RankOld
|
||||
sResponse.Rank.New = iStats.RankNew
|
||||
sResponse.Flash.Total.Enemy = iStats.FlashTotalEnemy
|
||||
sResponse.Flash.Total.Team = iStats.FlashTotalTeam
|
||||
sResponse.Flash.Total.Self = iStats.FlashTotalSelf
|
||||
sResponse.Flash.Duration.Enemy = iStats.FlashDurationEnemy
|
||||
sResponse.Flash.Duration.Team = iStats.FlashDurationTeam
|
||||
sResponse.Flash.Duration.Self = iStats.FlashDurationSelf
|
||||
|
||||
if !iStats.Edges.Players.VacDate.IsZero() {
|
||||
switch s := sResponse.Player.(type) {
|
||||
case PlayerResponse:
|
||||
s.VACDate = iStats.Edges.Players.VacDate
|
||||
}
|
||||
}
|
||||
|
||||
tmpStats = append(tmpStats, sResponse)
|
||||
}
|
||||
mResponse.Stats = tmpStats
|
||||
|
||||
err = utils.SendJSON(mResponse, w)
|
||||
if err != nil {
|
||||
@@ -461,13 +553,17 @@ func main() {
|
||||
|
||||
db.Client, err = ent.Open(conf.Db.Driver, conf.Db.ConnectTo)
|
||||
if err != nil {
|
||||
log.Panicf("Failed to open database %s: %v", "opencsgo.db", err)
|
||||
log.Panicf("Failed to open database %s: %v", conf.Db.ConnectTo, err)
|
||||
}
|
||||
defer func(dbSQLite *ent.Client) {
|
||||
_ = dbSQLite.Close()
|
||||
}(db.Client)
|
||||
|
||||
if err := db.Client.Schema.Create(context.Background(), migrate.WithDropIndex(true), migrate.WithDropColumn(true)); err != nil {
|
||||
if err := db.Client.Schema.Create(
|
||||
context.Background(),
|
||||
migrate.WithDropIndex(true),
|
||||
migrate.WithDropColumn(true),
|
||||
); err != nil {
|
||||
log.Panicf("Automigrate failed: %v", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user