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]) } }