/* * 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 . */ 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]Node 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 } gb := &graphBuilder{ refs: refs, nodeMap: make(NodeMap), nodes: nil, edges: nil, } 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 } func (gb *graphBuilder) prepareGraph() error { gb.nodes = prepareNodes(gb.nodeMap, func(node Node) Node { if node.Id == 0 { var green string green = "#f57900" 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 { id := gb.addNode(name, "#ef2929") if id < 0 { return nil } if ref, e := gb.refs[name]; e { for _, item := range ref { gb.addNode(item.Name, "#fce94f") } } for key, references := range gb.refs { for _, item := range references { if name == item.Name { gb.addNode(key, "#ad7fa8") } } } return nil } func prepareEdges(refs Refs, nodeMap NodeMap) []Edge { var edges []Edge edgeSet := make(map[Edge]bool) for key, references := range refs { if to, e := nodeMap[key]; e && to.Id >= 0 { for _, item := range references { if from, e := nodeMap[item.Name]; e && from.Id >= 0 { edge := Edge{ From: from.Id, To: to.Id, } 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 _, node := range nodeMap { if node.Id < 0 { continue } nodes = append(nodes, apply(Node{ Id: node.Id, Label: node.Label, Title: node.Title, Color: node.Color, Opacity: node.Opacity, })) } return nodes } func (gb *graphBuilder) prepareNodeMap() { for key, references := range gb.refs { gb.addNode(key, "#5e8") for _, item := range references { gb.addNode(item.Name, "#403") } } } func (gb *graphBuilder) addNode(key string, color string) int { if _, e := gb.nodeMap[key]; !e { color := color title:= strings.Replace(key, "_", " ", -1) gb.nodeMap[key] = Node{gb.nodeCount, key, title, &color, 1} gb.nodeCount += 1 } return gb.nodeMap[key].Id }