Fix SCUM companion trajectory storage

This commit is contained in:
npc0-hue
2026-08-31 15:42:16 +08:00
parent bc927a5144
commit ea4e780562
26 changed files with 1028 additions and 112 deletions
@@ -0,0 +1,80 @@
package companion
import (
"context"
"testing"
"time"
)
type trajectorySourceFixture struct {
positions []map[string]any
vehicles []map[string]any
limits []int
}
func (source *trajectorySourceFixture) ReadPositionRows(_ context.Context, limit int) ([]map[string]any, error) {
source.limits = append(source.limits, limit)
return source.positions, nil
}
func (source *trajectorySourceFixture) ReadVehicleRows(_ context.Context, limit int) ([]map[string]any, error) {
source.limits = append(source.limits, limit)
return source.vehicles, nil
}
type trajectoryStoreFixture struct {
ensureCalls int
samples []TrajectorySample
}
func (store *trajectoryStoreFixture) EnsureSchema(context.Context) error {
store.ensureCalls++
return nil
}
func (store *trajectoryStoreFixture) StorePositionRows(_ context.Context, serverInstanceID string, rows []map[string]any, sampledAt time.Time) (int, error) {
samples, err := TrajectorySamplesFromPositionRows(serverInstanceID, rows, sampledAt)
if err != nil {
return 0, err
}
store.samples = append(store.samples, samples...)
return len(samples), nil
}
func (store *trajectoryStoreFixture) StoreVehicleRows(_ context.Context, serverInstanceID string, rows []map[string]any, sampledAt time.Time) (int, error) {
samples, err := TrajectorySamplesFromVehicleRows(serverInstanceID, rows, sampledAt)
if err != nil {
return 0, err
}
store.samples = append(store.samples, samples...)
return len(samples), nil
}
func TestTrajectoryCollectorStoresRawSCUMWorldCoordinates(t *testing.T) {
sampledAt := time.Date(2026, 8, 31, 3, 30, 0, 0, time.UTC)
source := &trajectorySourceFixture{
positions: []map[string]any{{"subjectType": "player", "subjectId": "76561198000000001", "gamePlayerId": "player-1", "x": 123.25, "y": -456.5, "z": 7.75, "observedAt": "2026-08-31T03:29:59Z"}},
vehicles: []map[string]any{{"vehicleId": "vehicle-1", "entityId": "entity-1", "className": "BPC_Laika_C", "label": "Laika", "x": -10.5, "y": 20.25, "z": 0}},
}
store := &trajectoryStoreFixture{}
collector := &TrajectoryCollector{Source: source, Store: store, ServerInstanceID: "server-1", MaxRows: 777, Now: func() time.Time { return sampledAt }}
report, err := collector.CollectOnce(context.Background())
if err != nil {
t.Fatalf("collect trajectories: %v", err)
}
if report.PositionRows != 1 || report.VehicleRows != 1 || report.StoredSamples != 2 || report.Reason != "raw world coordinates stored" {
t.Fatalf("unexpected collection report: %+v", report)
}
if store.ensureCalls != 1 || len(source.limits) != 2 || source.limits[0] != 777 || source.limits[1] != 777 {
t.Fatalf("collector did not use bounded source/store once: ensure=%d limits=%v", store.ensureCalls, source.limits)
}
if len(store.samples) != 2 {
t.Fatalf("expected two trajectory samples, got %+v", store.samples)
}
if store.samples[0].WorldX != 123.25 || store.samples[0].WorldY != -456.5 || store.samples[0].WorldZ == nil || *store.samples[0].WorldZ != 7.75 {
t.Fatalf("player coordinates were changed before storage: %+v", store.samples[0])
}
if store.samples[1].SubjectType != "vehicle" || store.samples[1].WorldX != -10.5 || store.samples[1].WorldY != 20.25 || store.samples[1].Source != "plugin.sql.scum.vehicles" {
t.Fatalf("vehicle coordinates were changed before storage: %+v", store.samples[1])
}
}