wiki/graph.go
Peter Stuifzand 5bf14bd1d4
All checks were successful
continuous-integration/drone/push Build is passing
Show graph on edit page for neighbors two edges out
2020-07-05 20:34:36 +02:00

139 lines
2.4 KiB
Go

package main
import (
"encoding/json"
"os"
"path/filepath"
"strings"
)
type graphBuilder struct {
refs Refs
nodeMap NodeMap
nodeCount int
nodes []Node
edges []Edge
}
type NodeMap map[string]int
func NewGraphBuilder(mp PagesRepository) (*graphBuilder, error) {
refs := make(Refs)
f, err := os.Open(filepath.Join(mp.(*FilePages).dirname, "backrefs.json"))
if err != nil {
return nil, err
}
defer f.Close()
err = json.NewDecoder(f).Decode(&refs)
if err != nil {
return nil, err
}
return &graphBuilder{
refs: refs,
nodeMap: make(NodeMap),
nodes: nil,
edges: nil,
}, nil
}
func (gb *graphBuilder) prepareGraph() error {
gb.nodes = prepareNodes(gb.nodeMap, func(node Node) Node {
if node.Id == 0 {
var green string
green = "green"
node.Color = &green
}
return node
})
gb.edges = prepareEdges(gb.refs, gb.nodeMap)
return nil
}
func (gb *graphBuilder) RemoveNode(name string) {
delete(gb.nodeMap, name)
}
func (gb *graphBuilder) RemoveNodeWithSuffix(suffix string) {
for k, _ := range gb.nodeMap {
if strings.HasSuffix(k, suffix) {
delete(gb.nodeMap, k)
}
}
}
func (gb *graphBuilder) buildFromCenter(name string) error {
_ = gb.addNode(name)
if ref, e := gb.refs[name]; e {
for _, item := range ref {
gb.addNode(item.Name)
}
}
for key, references := range gb.refs {
for _, item := range references {
if name == item.Name {
gb.addNode(key)
}
}
}
return nil
}
func prepareEdges(refs Refs, nodeMap NodeMap) []Edge {
var edges []Edge
edgeSet := make(map[Edge]bool)
for key, references := range refs {
if toID, e := nodeMap[key]; e {
for _, item := range references {
if fromID, e := nodeMap[item.Name]; e {
edge := Edge{
From: fromID,
To: toID,
}
if _, e := edgeSet[edge]; !e {
edgeSet[edge] = true
edges = append(edges, edge)
}
}
}
}
}
return edges
}
func prepareNodes(nodeMap NodeMap, apply func(node Node) Node) []Node {
var nodes []Node
for name, id := range nodeMap {
nodes = append(nodes, apply(Node{
Id: id,
Label: name,
Color: nil,
}))
}
return nodes
}
func (gb *graphBuilder) prepareNodeMap() {
for key, references := range gb.refs {
gb.addNode(key)
for _, item := range references {
gb.addNode(item.Name)
}
}
}
func (gb *graphBuilder) addNode(key string) int {
if _, e := gb.nodeMap[key]; !e {
gb.nodeMap[key] = gb.nodeCount
gb.nodeCount += 1
}
return gb.nodeMap[key]
}