74 lines
1.9 KiB
Go
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)
|
|
}
|