Files
foundry-core/internal/platform/member_drop.go
T
codex-bot 09c78d3ab8
Foundry Go checks / check (push) Successful in 8m18s
Foundry Go checks / check (pull_request) Successful in 6m16s
Accept final member positions in ownership transactions
2026-11-06 22:46:46 +08:00

74 lines
1.9 KiB
Go

package platform
import (
"encoding/json"
"fmt"
"math"
)
// Positions are expressed in the source board's local coordinates. The existing
// ownership transaction converts them into destination coordinates exactly once.
type memberDropPosition struct {
X float64 `json:"x"`
Y float64 `json:"y"`
}
func validMemberDropPositions(ids []string, positions map[string]memberDropPosition) bool {
if positions == nil {
return true
} // Backward-compatible old clients.
if len(positions) != len(ids) {
return false
}
seen := map[string]bool{}
for _, id := range ids {
p, ok := positions[id]
if !ok || seen[id] || math.IsNaN(p.X) || math.IsNaN(p.Y) || math.IsInf(p.X, 0) || math.IsInf(p.Y, 0) || math.Abs(p.X) > 1e6 || math.Abs(p.Y) > 1e6 {
return false
}
seen[id] = true
}
return true
}
func positionMemberDrop(raw json.RawMessage, positions map[string]memberDropPosition) (json.RawMessage, error) {
var doc map[string]any
if err := json.Unmarshal(raw, &doc); err != nil {
return nil, err
}
found := 0
nodes, ok := doc["nodes"].([]any)
if !ok {
return nil, errGraphOwnership
}
for _, v := range nodes {
n, ok := v.(map[string]any)
if !ok {
return nil, errGraphOwnership
}
id, _ := n["id"].(string)
if p, ok := positions[id]; ok {
n["position"] = map[string]any{"x": p.X, "y": p.Y}
found++
}
}
if found != len(positions) {
return nil, errGraphOwnership
}
return json.Marshal(doc)
}
func (p *memberDropPosition) UnmarshalJSON(raw []byte) error {
var fields map[string]json.RawMessage
if err := json.Unmarshal(raw, &fields); err != nil {
return err
}
if len(fields) != 2 || fields["x"] == nil || fields["y"] == nil || string(fields["x"]) == "null" || string(fields["y"]) == "null" {
return fmt.Errorf("invalid member position")
}
if err := json.Unmarshal(fields["x"], &p.X); err != nil {
return err
}
return json.Unmarshal(fields["y"], &p.Y)
}