Skip to content

Commit

Permalink
Remove logparse based match tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
leighmacdonald committed Dec 28, 2024
1 parent c1268f3 commit 8356c65
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 316 deletions.
1 change: 0 additions & 1 deletion internal/cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ func serveCmd() *cobra.Command { //nolint:maintidx
appeals := appeal.NewAppealUsecase(appeal.NewAppealRepository(dbConn), banUsecase, personUsecase, notificationUsecase, configUsecase)

matchRepo := match.NewMatchRepository(eventBroadcaster, dbConn, personUsecase, serversUC, notificationUsecase, stateUsecase, weaponsMap)
go matchRepo.Start(ctx)

matchUsecase := match.NewMatchUsecase(matchRepo, stateUsecase, serversUC, notificationUsecase)

Expand Down
2 changes: 1 addition & 1 deletion internal/demo/demo_usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func (d demoUsecase) CreateFromAsset(ctx context.Context, asset domain.Asset, se
}

for key := range demoDetail.State.Users {
intStats[key] = gin.H{}
intStats[fmt.Sprintf("%d", key)] = gin.H{}

Check failure on line 299 in internal/demo/demo_usecase.go

View workflow job for this annotation

GitHub Actions / lint-golangci

fmt.Sprintf can be replaced with faster strconv.Itoa (perfsprint)
}

timeStr := fmt.Sprintf("%s-%s", namePartsAll[0], namePartsAll[1])
Expand Down
69 changes: 60 additions & 9 deletions internal/domain/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package domain

import (
"context"
"github.com/leighmacdonald/gbans/pkg/logparse"
"github.com/leighmacdonald/steamid/v4/steamid"
"time"

"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -54,18 +56,20 @@ type DemoFile struct {
AssetID uuid.UUID `json:"asset_id"`
}

const DemoType = "HL2DEMO"

type DemoInfo struct {
DemoID int64
Title string
AssetID uuid.UUID
}

type DemoPlayer struct {
Classes struct{} `json:"classes"`
Name string `json:"name"`
UserID int `json:"userId"` //nolint:tagliatelle
SteamID string `json:"steamId"` //nolint:tagliatelle
Team string `json:"team"`
Classes map[logparse.PlayerClass]int `json:"classes"`
Name string `json:"name"`
UserID int `json:"userId"` //nolint:tagliatelle
SteamID steamid.SteamID `json:"steamId"` //nolint:tagliatelle
Team logparse.Team `json:"team"`
}

type DemoHeader struct {
Expand All @@ -82,10 +86,57 @@ type DemoHeader struct {
Signon int `json:"signon"`
}

type DemoWeaponDetail struct {
Kills int `json:"kills"`
Damage int `json:"damage"`
Shots int `json:"shots"`
Hits int `json:"hits"`
Backstabs int `json:"backstabs,`

Check failure on line 94 in internal/domain/demo.go

View workflow job for this annotation

GitHub Actions / lint-golangci

structtag: struct field tag `json:"backstabs,` not compatible with reflect.StructTag.Get: bad syntax for struct tag value (govet)
Headshots int `json:"headshots"`
Airshots int `json:"airshots"`
}

type DemoPlayerSummaries struct {
Points int `json:"points"`
Kills int `json:"kills"`
Assists int `json:"assists"`
Deaths int `json:"deaths"`
BuildingsDestroyed int `json:"buildings_destroyed"`
Captures int `json:"captures"`
Defenses int `json:"defenses"`
Dominations int `json:"dominations"`
Revenges int `json:"revenges"`
Ubercharges int `json:"ubercharges"`
Headshots int `json:"headshots"`
Teleports int `json:"teleports"`
Healing int `json:"healing"`
Backstabs int `json:"backstabs"`
BonusPoints int `json:"bonus_points"`
Support int `json:"support"`
DamgageDealt int `json:"damgage_dealt"`
WeaponMap map[logparse.Weapon]DemoWeaponDetail `json:"weapon_map"`
}

type DemoChatMessage struct {
}

type DemoMatchSummary struct {
ScoreBlu int `json:"score_blu"`
ScoreRed int `json:"score_red"`
Chat []DemoChatMessage `json:"chat"`
}

type DemoRoundSummary struct {
}

type DemoState struct {
DemoPlayerSummaries map[int]DemoPlayerSummaries `json:"player_summaries"` //nolint:tagliatelle
Users map[int]DemoPlayer `json:"users"`
DemoMatchSummary DemoMatchSummary `json:"match_summary"` //nolint:tagliatelle
DemoRoundSummary DemoRoundSummary `json:"round_summary"`

Check failure on line 136 in internal/domain/demo.go

View workflow job for this annotation

GitHub Actions / lint-golangci

json(snake): got 'round_summary' want 'demo_round_summary' (tagliatelle)
}

type DemoDetails struct {
State struct {
PlayerSummaries struct{} `json:"player_summaries"`
Users map[string]DemoPlayer `json:"users"`
} `json:"state"`
State DemoState `json:"state"`
Header DemoHeader `json:"header"`
}
23 changes: 2 additions & 21 deletions internal/domain/match.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,7 @@ import (
"golang.org/x/exp/slices"
)

type MatchTriggerType int

const (
MatchTriggerStart MatchTriggerType = 1
MatchTriggerEnd MatchTriggerType = 2
)

type MatchTrigger struct {
Type MatchTriggerType
UUID uuid.UUID
Server Server
MapName string
DemoName string
}

type MatchRepository interface {
Start(ctx context.Context)
StartMatch(startTrigger MatchTrigger)
EndMatch(endTrigger MatchTrigger)
Matches(ctx context.Context, opts MatchesQueryOpts) ([]MatchSummary, int64, error)
MatchGetByID(ctx context.Context, matchID uuid.UUID, match *MatchResult) error
MatchSave(ctx context.Context, match *logparse.Match, weaponMap fp.MutexMap[logparse.Weapon, int]) error
Expand All @@ -56,8 +38,7 @@ type MatchRepository interface {
GetMatchIDFromServerID(serverID int) (uuid.UUID, bool)
}
type MatchUsecase interface {
StartMatch(server Server, mapName string, demoName string) (uuid.UUID, error)
EndMatch(ctx context.Context, serverID int) (uuid.UUID, error)
CreateFromDemo(ctx context.Context, serverID int, details DemoDetails) (MatchSummary, error)
GetMatchIDFromServerID(serverID int) (uuid.UUID, bool)
Matches(ctx context.Context, opts MatchesQueryOpts) ([]MatchSummary, int64, error)
MatchGetByID(ctx context.Context, matchID uuid.UUID, match *MatchResult) error
Expand Down Expand Up @@ -443,7 +424,7 @@ type PlayerMedicStats struct {
type CommonPlayerStats struct {
SteamID steamid.SteamID `json:"steam_id"`
Name string `json:"name"`
AvatarHash string `json:"avatar_hash"`
AvatarHash string `json:"avatar_hash"` //todo make

Check failure on line 427 in internal/domain/match.go

View workflow job for this annotation

GitHub Actions / lint-golangci

commentFormatting: put a space between `//` and comment text (gocritic)
Kills int `json:"kills"`
Assists int `json:"assists"`
Deaths int `json:"deaths"`
Expand Down
62 changes: 0 additions & 62 deletions internal/match/match_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/gofrs/uuid/v5"
"github.com/jackc/pgx/v5"
"github.com/leighmacdonald/gbans/internal/database"
"github.com/leighmacdonald/gbans/internal/discord"
"github.com/leighmacdonald/gbans/internal/domain"
"github.com/leighmacdonald/gbans/pkg/fp"
"github.com/leighmacdonald/gbans/pkg/logparse"
Expand All @@ -21,7 +20,6 @@ type matchRepository struct {
notifications domain.NotificationUsecase
servers domain.ServersUsecase
state domain.StateUsecase
summarizer *Summarizer
wm fp.MutexMap[logparse.Weapon, int]
events chan logparse.ServerEvent
broadcaster *fp.Broadcaster[logparse.EventType, logparse.ServerEvent]
Expand All @@ -44,69 +42,9 @@ func NewMatchRepository(broadcaster *fp.Broadcaster[logparse.EventType, logparse
events: make(chan logparse.ServerEvent),
}

matchRepo.summarizer = newMatchSummarizer(matchRepo.events, matchRepo.onMatchComplete)

return matchRepo
}

func (r *matchRepository) StartMatch(startTrigger domain.MatchTrigger) {
r.summarizer.triggers <- startTrigger
}

func (r *matchRepository) EndMatch(endTrigger domain.MatchTrigger) {
r.summarizer.triggers <- endTrigger
}

func (r *matchRepository) onMatchComplete(ctx context.Context, matchContext *activeMatchContext) error {
const minPlayers = 6

server, found := r.state.ByServerID(matchContext.server.ServerID)

if found && server.Name != "" {
matchContext.match.Title = server.Name
}

fullServer, err := r.servers.Server(ctx, server.ServerID)
if err != nil {
return errors.Join(err, domain.ErrLoadServer)
}

if !fullServer.EnableStats {
return nil
}

if len(matchContext.match.PlayerSums) < minPlayers {
return domain.ErrInsufficientPlayers
}

if matchContext.match.TimeStart == nil || matchContext.match.MapName == "" {
return domain.ErrIncompleteMatch
}

if errSave := r.MatchSave(ctx, &matchContext.match, r.wm); errSave != nil {
if errors.Is(errSave, domain.ErrInsufficientPlayers) {
return domain.ErrInsufficientPlayers
}

return errors.Join(errSave, domain.ErrSaveMatch)
}

var result domain.MatchResult
if errResult := r.MatchGetByID(ctx, matchContext.match.MatchID, &result); errResult != nil {
return errors.Join(errResult, domain.ErrLoadMatch)
}

r.notifications.Enqueue(ctx, domain.NewDiscordNotification(
domain.ChannelPublicMatchLog,
discord.MatchMessage(result, "")))

return nil
}

func (r *matchRepository) Start(ctx context.Context) {
r.summarizer.Start(ctx)
}

func (r *matchRepository) GetMatchIDFromServerID(serverID int) (uuid.UUID, bool) {
return r.matchUUIDMap.Get(serverID)
}
Expand Down
73 changes: 0 additions & 73 deletions internal/match/match_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/gin-gonic/gin"
"github.com/gofrs/uuid/v5"
"github.com/leighmacdonald/gbans/internal/domain"
"github.com/leighmacdonald/gbans/internal/httphelper"
"github.com/leighmacdonald/gbans/pkg/log"
Expand Down Expand Up @@ -41,78 +40,6 @@ func NewMatchHandler(ctx context.Context, engine *gin.Engine, matches domain.Mat
authed.GET("/api/stats/player/:steam_id/weapons", handler.onAPIGetPlayerWeaponStatsOverall())
authed.GET("/api/stats/player/:steam_id/classes", handler.onAPIGetPlayerClassStatsOverall())
authed.GET("/api/stats/player/:steam_id/overall", handler.onAPIGetPlayerStatsOverall())
authed.POST("/api/sm/match/start", handler.onAPIPostMatchStart())
authed.GET("/api/sm/match/end", handler.onAPIPostMatchEnd())
}
}

func (h matchHandler) onAPIPostMatchEnd() gin.HandlerFunc {
type endMatchResponse struct {
URL string `json:"url"`
}

return func(ctx *gin.Context) {
serverID, errServerID := httphelper.GetIntParam(ctx, "server_id")
if errServerID != nil {
httphelper.HandleErrInternal(ctx)
slog.Warn("Failed to get server_id", log.ErrAttr(errServerID))

return
}

matchUUID, errEnd := h.matches.EndMatch(ctx, serverID)
if errEnd != nil {
httphelper.ResponseAPIErr(ctx, http.StatusInternalServerError, domain.ErrUnknownServerID)
slog.Error("Failed to end match", log.ErrAttr(errEnd))

return
}

ctx.JSON(http.StatusOK, endMatchResponse{URL: h.config.ExtURLRaw("/match/%s", matchUUID.String())})
}
}

func (h matchHandler) onAPIPostMatchStart() gin.HandlerFunc {
type matchStartRequest struct {
MapName string `json:"map_name"`
DemoName string `json:"demo_name"`
}

type matchStartResponse struct {
MatchID uuid.UUID `json:"match_id"`
}

return func(ctx *gin.Context) {
var req matchStartRequest
if !httphelper.Bind(ctx, &req) {
return
}

serverID, errServerID := httphelper.GetIntParam(ctx, "server_id")
if errServerID != nil {
httphelper.ResponseAPIErr(ctx, http.StatusInternalServerError, domain.ErrUnknownServerID)
slog.Warn("Failed to get server_id", log.ErrAttr(errServerID))

return
}

server, errServer := h.servers.Server(ctx, serverID)
if errServer != nil {
httphelper.ResponseAPIErr(ctx, http.StatusInternalServerError, domain.ErrUnknownServerID)
slog.Error("Failed to get server", log.ErrAttr(errServer))

return
}

matchUUID, errMatch := h.matches.StartMatch(server, req.MapName, req.DemoName)
if errMatch != nil {
httphelper.ResponseAPIErr(ctx, http.StatusInternalServerError, domain.ErrUnknownServerID)
slog.Error("Failed to start match", log.ErrAttr(errMatch))

return
}

ctx.JSON(http.StatusOK, matchStartResponse{MatchID: matchUUID})
}
}

Expand Down
Loading

0 comments on commit 8356c65

Please sign in to comment.