diff --git a/internal/service/ops.go b/internal/service/ops.go index 081b1ab..5c7340d 100644 --- a/internal/service/ops.go +++ b/internal/service/ops.go @@ -605,17 +605,16 @@ type DescribeGroup struct { // DaysToMaturity is the plant's, when the catalog knows it — with PlantedAt, // enough to say when the harvest is due. DaysToMaturity *int `json:"daysToMaturity,omitempty"` - // Each lists the plops individually (id, version, location) only when the - // group has at most maxListedPlops of them. + // Each lists the plops individually (id, version, position, location) only + // when the group has at most maxListedPlops of them. Each []DescribePlanting `json:"each,omitempty"` } // DescribePlanting is one plop with its position and a rough compass location. // ID + Version let an agent address a single plop — remove it or move it — the -// same way DescribeObject.Version lets it edit an object; XCM/YCM (the object's -// local frame) let a move keep the layout the plops had, which "north, south" -// alone cannot: asked to move four tomatoes in a column "keeping the same -// spacing", the live assistant re-laid them as two pairs for want of these. +// same way DescribeObject.Version lets it edit an object. XCM/YCM are in the +// object's local frame: they are what lets a move keep the layout the plops +// had, which the compass word alone ("north", "south") cannot. type DescribePlanting struct { ID int64 `json:"id"` Version int64 `json:"version"` diff --git a/internal/service/ops_test.go b/internal/service/ops_test.go index 2a8b2b3..8ba0982 100644 --- a/internal/service/ops_test.go +++ b/internal/service/ops_test.go @@ -628,14 +628,20 @@ func TestDescribeGardenGroupsByPlant(t *testing.T) { if want := 2*derivedCount(20, 25) + 3; ba.Plants != want { t.Errorf("basil plants = %d, want %d", ba.Plants, want) } + // The position is what lets a move keep the layout; "south" alone can't. The + // three basil plops were placed at exactly these local points. + placedAt := map[[2]float64]bool{{-100, 100}: true, {0, 150}: true, {100, 100}: true} for _, e := range ba.Each { if e.PlantedAt == "" || e.Version == 0 || e.ID == 0 { t.Errorf("listed plop %+v is missing id, version or date", e) } - // The position is what lets a move keep the layout; "south" alone can't. - if e.YCM < 100 || (e.XCM != -100 && e.XCM != 0 && e.XCM != 100) { - t.Errorf("listed plop %+v doesn't carry the position it was placed at", e) + if !placedAt[[2]float64{e.XCM, e.YCM}] { + t.Errorf("listed plop %+v is not at a position a basil was placed at", e) } + delete(placedAt, [2]float64{e.XCM, e.YCM}) + } + if len(placedAt) != 0 { + t.Errorf("positions never listed: %v", placedAt) } // The big group's ids are a call away, narrowed to one plant.