wiki/graph.go

171 lines
3.6 KiB
Go
Raw Permalink Normal View History

2021-08-07 17:13:10 +00:00
/*
* Wiki - A wiki with editor
* Copyright (c) 2021-2021 Peter Stuifzand
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2020-07-05 12:12:15 +00:00
package main
import (
"encoding/json"
"os"
"path/filepath"
"strings"
)
type graphBuilder struct {
refs Refs
nodeMap NodeMap
nodeCount int
nodes []Node
edges []Edge
2020-07-05 12:12:15 +00:00
}
2020-07-05 19:18:42 +00:00
type NodeMap map[string]Node
2020-07-05 12:12:15 +00:00
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
}
2020-07-07 22:45:06 +00:00
gb := &graphBuilder{
2020-07-05 12:12:15 +00:00
refs: refs,
nodeMap: make(NodeMap),
2020-07-05 12:12:15 +00:00
nodes: nil,
edges: nil,
2020-07-07 22:45:06 +00:00
}
gb.nodeMap["Daily_Notes"] = Node{Id: -1}
gb.nodeMap["TODO"] = Node{Id: -1}
gb.nodeMap["DONE"] = Node{Id: -1}
gb.nodeMap["Projects"] = Node{Id: -1}
return gb, nil
2020-07-05 12:12:15 +00:00
}
func (gb *graphBuilder) prepareGraph() error {
gb.nodes = prepareNodes(gb.nodeMap, func(node Node) Node {
if node.Id == 0 {
var green string
2020-07-05 19:18:42 +00:00
green = "#f57900"
node.Color = &green
}
return node
})
2020-07-05 12:12:15 +00:00
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) {
2021-08-17 20:38:25 +00:00
for k := range gb.nodeMap {
2020-07-05 12:12:15 +00:00
if strings.HasSuffix(k, suffix) {
delete(gb.nodeMap, k)
}
}
}
func (gb *graphBuilder) buildFromCenter(name string) error {
2020-07-07 22:45:06 +00:00
id := gb.addNode(name, "#ef2929")
if id < 0 {
return nil
}
if ref, e := gb.refs[name]; e {
for _, item := range ref {
2020-07-05 19:18:42 +00:00
gb.addNode(item.Name, "#fce94f")
}
}
for key, references := range gb.refs {
for _, item := range references {
if name == item.Name {
2020-07-05 19:18:42 +00:00
gb.addNode(key, "#ad7fa8")
}
}
}
return nil
}
2020-07-05 12:12:15 +00:00
func prepareEdges(refs Refs, nodeMap NodeMap) []Edge {
var edges []Edge
edgeSet := make(map[Edge]bool)
for key, references := range refs {
2020-07-07 22:45:06 +00:00
if to, e := nodeMap[key]; e && to.Id >= 0 {
2020-07-05 12:12:15 +00:00
for _, item := range references {
2020-07-07 22:45:06 +00:00
if from, e := nodeMap[item.Name]; e && from.Id >= 0 {
2020-07-05 12:12:15 +00:00
edge := Edge{
2020-07-05 19:18:42 +00:00
From: from.Id,
To: to.Id,
2020-07-05 12:12:15 +00:00
}
if _, e := edgeSet[edge]; !e {
edgeSet[edge] = true
edges = append(edges, edge)
}
}
}
}
}
return edges
}
func prepareNodes(nodeMap NodeMap, apply func(node Node) Node) []Node {
2020-07-05 12:12:15 +00:00
var nodes []Node
2020-07-05 19:18:42 +00:00
for _, node := range nodeMap {
2020-07-07 22:45:06 +00:00
if node.Id < 0 {
continue
}
nodes = append(nodes, apply(Node{
2020-07-05 19:18:42 +00:00
Id: node.Id,
Label: node.Label,
2021-08-17 20:38:25 +00:00
Title: node.Title,
2020-07-05 19:18:42 +00:00
Color: node.Color,
Opacity: node.Opacity,
}))
2020-07-05 12:12:15 +00:00
}
return nodes
}
func (gb *graphBuilder) prepareNodeMap() {
for key, references := range gb.refs {
2020-07-05 19:18:42 +00:00
gb.addNode(key, "#5e8")
2020-07-05 12:12:15 +00:00
for _, item := range references {
2020-07-05 19:18:42 +00:00
gb.addNode(item.Name, "#403")
2020-07-05 12:12:15 +00:00
}
}
}
2020-07-05 19:18:42 +00:00
func (gb *graphBuilder) addNode(key string, color string) int {
if _, e := gb.nodeMap[key]; !e {
2020-07-05 19:18:42 +00:00
color := color
2021-08-17 20:38:25 +00:00
title:= strings.Replace(key, "_", " ", -1)
gb.nodeMap[key] = Node{gb.nodeCount, key, title, &color, 1}
gb.nodeCount += 1
}
2020-07-05 12:12:15 +00:00
2020-07-05 19:18:42 +00:00
return gb.nodeMap[key].Id
2020-07-05 12:12:15 +00:00
}