package catalogue import ( "fmt" "sort" ) // An assignment as the passing of a seat reads it: a module on a machine, with its manifest. type Assignment struct { Node string Manifest Manifest } // SeatPass is one seat whose holder on record is assigned nowhere, and the only assignment that can take it. type SeatPass struct { Seat Seat From Held To Held } // SeatsToPassOn reads the mesh for seats held once whose holder on record has left (novox/hq ADR 0449 §4). // // **A holder on record that is assigned on no machine holds nothing, and a seat that answers nothing is // the day a delivery removed its module.** Of such a seat, exactly one assignment in the mesh able to hold // it (it claims the seat at its scope and CanHold accepts it) takes it over: that is a pass, and the caller // records it and writes the hand act. With no such assignment the record stays; with two or more nothing is // recorded and the answer says so, naming both and the `seat --to` that settles it. A holder still assigned // anywhere changes nothing: the other claimants stand beside it, eligible and silent (ADR 0131). Only mesh // seats held once are read: a replicated seat's holders are added by an act (ADR 0223), a kinded bench is held // by its claims, and a seat with several holders on record is a store that disagrees with the mesh (refused // by the resolver). func SeatsToPassOn(holdings []Held, assignments []Assignment) ([]SeatPass, []string) { assigned := map[string]bool{} for _, a := range assignments { assigned[a.Manifest.Module] = true } bySeat := map[string][]Held{} var order []string for _, h := range holdings { s, ok := SeatNamed(h.Claim) if !ok || s.Replicated || s.Scope != ScopeMesh || h.Scope != ScopeMesh || KindedBenches[s.Name] { continue } if _, seen := bySeat[s.Name]; !seen { order = append(order, s.Name) } bySeat[s.Name] = append(bySeat[s.Name], h) } sort.Strings(order) var passes []SeatPass var said []string for _, name := range order { recs := bySeat[name] if len(recs) != 1 || assigned[recs[0].Module] { continue } seat, _ := SeatNamed(name) var claimants []Held for _, a := range assignments { if CanHold(a.Manifest, seat) != nil { continue } claimants = append(claimants, Held{Claim: seat.Name, Scope: seat.Scope, Node: a.Node, Module: a.Manifest.Module}) } sort.Slice(claimants, func(i, j int) bool { if claimants[i].Node != claimants[j].Node { return claimants[i].Node < claimants[j].Node } return claimants[i].Module < claimants[j].Module }) switch len(claimants) { case 0: case 1: passes = append(passes, SeatPass{Seat: seat, From: recs[0], To: claimants[0]}) default: said = append(said, fmt.Sprintf( "%s on %s is on record as the holder of %q and is assigned nowhere, and %s on %s and %s on %s both claim it "+ "— nothing is recorded; `seat %s --to /` records the one that holds it", recs[0].Module, recs[0].Node, seat.Name, claimants[0].Module, claimants[0].Node, claimants[1].Module, claimants[1].Node, seat.Name)) } } return passes, said }