| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 | package mainimport (	"fmt"	"github.com/beanzilla/gonode"	"golang.org/x/exp/slices")type TravelPath struct {	N_Path        *gonode.Node `json:"-"`	N_Destination *gonode.Node `json:"-"`	Path          []string     `json:"path"`	Destination   string       `json:"destination"`}func (t *TravelPath) String() string {	result := ""	for _, path := range t.Path {		if result != "" {			result += " > "		}		result += path	}	if result != "" {		result += " >> "	}	result += t.Destination	return result}func (t *TravelPath) Parse(n *gonode.Node) error {	txt := fmt.Sprintf("%v", n.Data())	switch Key(txt) {	case "playtime":		if !n.HasTag("insert", "travel") {			n.AddTag("insert", "travel")		}	case "travel":		if t.N_Path == nil {			t.N_Path = n.Parent()		}		t.Path = append(t.Path, Value(txt))		if !n.HasTag("replace", "travel") {			n.AddTag("replace", "travel")		}	case "travel destination":		t.N_Destination = n		t.Destination = Value(txt)	}	return nil}func (t *TravelPath) Update() error {	if t.N_Path == nil {		return fmt.Errorf("missing node(s), can't update")	}	replaced := false	// Replace nodes we've seen before (this takes care of if we didn't really change anything)	// Problems: New items, less items	for _, path := range t.Path {		replaced = false		idx := 0	FIND_A_NODE:		for kid := range t.N_Path.Iter() {			if kid.HasTag("replace", "travel") {				kid.SetData(fmt.Sprintf("travel %s", Format(path)))				kid.RmTag("replace", "travel")				replaced = true				break FIND_A_NODE			}			idx += 1		}		if !replaced {			t.N_Path.NewChildWithData(fmt.Sprintf("travel %s", Format(path)))		}	}	// Cleanup less items (this will remove old/stale stuff)	idxs := []int{}	idx := 0	for idx != -1 {		idx = t.N_Path.ChildIndexByTag("replace", "travel")		if !slices.Contains(idxs, idx) {			idxs = append(idxs, idx)		} else {			break		}	}	t.N_Path.RmChild(idxs...)	// Update the destination	if t.Destination != "" && t.N_Destination != nil {		// We have a destination and a node for it		t.N_Destination.SetData(fmt.Sprintf("%s %s", Format("travel destination"), Format(t.Destination)))	} else if t.Destination == "" && t.N_Destination != nil {		// We have no destination but a node		t.N_Destination.Detach()		t.N_Destination.Destroy()	} else if t.Destination != "" && t.N_Destination == nil {		// We have a destination but no node for it		t.N_Path.NewChildWithData(fmt.Sprintf("%s %s", Format("travel destination"), Format(t.Destination)))	}	return nil}
 |