1 /*
2 knowledge_graph.cpp MindForger thinking notebook
3
4 Copyright (C) 2016-2020 Martin Dvorak <martin.dvorak@mindforger.com>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "knowledge_graph.h"
20
21 namespace m8r {
22
23 using namespace std;
24
25 /*
26 * Knowledge SUB graph
27 */
28
KnowledgeSubGraph(KnowledgeGraphNode * centralNode,int maxSubgraphNodes)29 KnowledgeSubGraph::KnowledgeSubGraph(KnowledgeGraphNode* centralNode, int maxSubgraphNodes)
30 : centralNode(centralNode), maxSubgraphNodes(maxSubgraphNodes)
31 {
32 this->count = maxSubgraphNodes-1;
33 }
34
35 /*
36 * Knowledge graph
37 */
38
KnowledgeGraph(Mind * mind,long unsigned mindColor,long unsigned coreColor,long unsigned outlinesColor,long unsigned notesColor)39 KnowledgeGraph::KnowledgeGraph(
40 Mind* mind,
41 long unsigned mindColor,
42 long unsigned coreColor,
43 long unsigned outlinesColor,
44 long unsigned notesColor
45 )
46 : mind{mind}
47 {
48 mindNode = new KnowledgeGraphNode{KnowledgeGraphNodeType::MIND, "MIND", mindColor, 5};
49 tagsNode = new KnowledgeGraphNode{KnowledgeGraphNodeType::TAGS, "tags"};
50 outlinesNode = new KnowledgeGraphNode{KnowledgeGraphNodeType::OUTLINES, "notebooks"};
51 notesNode = new KnowledgeGraphNode{KnowledgeGraphNodeType::NOTES, "notes"};
52 //limboNode = new KnowledgeGraphNode{KnowledgeGraphNodeType::LIMBO, "limbo"};
53 //stencilsNode = new KnowledgeGraphNode{KnowledgeGraphNodeType::STENCILS, "stencils"};
54
55 this->coreColor = coreColor;
56 this->outlinesColor = outlinesColor;
57 this->notesColor = notesColor;
58 }
59
~KnowledgeGraph()60 KnowledgeGraph::~KnowledgeGraph()
61 {
62 delete mindNode;
63 delete tagsNode;
64 delete outlinesNode;
65 delete notesNode;
66 //delete limboNode;
67 //delete stencilsNode;
68 }
69
getNode(KnowledgeGraphNodeType type)70 KnowledgeGraphNode* KnowledgeGraph::getNode(KnowledgeGraphNodeType type)
71 {
72 switch(type) {
73 case KnowledgeGraphNodeType::MIND:
74 return mindNode;
75 case KnowledgeGraphNodeType::OUTLINES:
76 return outlinesNode;
77 case KnowledgeGraphNodeType::NOTES:
78 return notesNode;
79 case KnowledgeGraphNodeType::TAGS:
80 return tagsNode;
81 /*
82 case KnowledgeGraphNodeType::STENCILS:
83 return stencilsNode;
84 case KnowledgeGraphNodeType::LIMBO:
85 return limboNode;
86 case KnowledgeGraphNodeType::STENCIL:
87 */
88 case KnowledgeGraphNodeType::OUTLINE:
89 case KnowledgeGraphNodeType::NOTE:
90 case KnowledgeGraphNodeType::TAG:
91 return nullptr;
92 }
93
94 return nullptr;
95 }
96
getNode(Outline * o)97 KnowledgeGraphNode* KnowledgeGraph::getNode(Outline* o)
98 {
99 KnowledgeGraphNode* k = new KnowledgeGraphNode{
100 KnowledgeGraphNodeType::OUTLINE,
101 o->getName(),
102 outlinesColor,
103 static_cast<unsigned int>(o->getNotesCount())};
104 k->setThing(o);
105
106 return k;
107 }
108
getNode(Note * n)109 KnowledgeGraphNode* KnowledgeGraph::getNode(Note* n)
110 {
111 KnowledgeGraphNode* k = new KnowledgeGraphNode{KnowledgeGraphNodeType::NOTE, n->getName(), notesColor};
112 k->setThing(n);
113 k->setCardinality(n->getOutline()->getDirectNoteChildrenCount(n));
114
115 return k;
116 }
117
118 // TODO this method leaks a lot - knowledge graph nodes
getRelatedNodes(KnowledgeGraphNode * centralNode,KnowledgeSubGraph & subgraph)119 void KnowledgeGraph::getRelatedNodes(KnowledgeGraphNode* centralNode, KnowledgeSubGraph& subgraph)
120 {
121 subgraph.clear();
122
123 // refresh core nodes cardinalities
124 tagsNode->setCardinality(static_cast<unsigned int>(mind->getTags().size()));
125 outlinesNode->setCardinality(mind->remind().getOutlinesCount());
126 notesNode->setCardinality(mind->remind().getNotesCount());
127 //stencilsNode->setCardinality(static_cast<unsigned int>(mind->remind().getStencils().size()));
128 //limboNode->...
129
130 // significant ontology things
131 if(centralNode == mindNode) {
132 subgraph.setCentralNode(mindNode);
133
134 subgraph.addChild(tagsNode);
135 subgraph.addChild(outlinesNode);
136 subgraph.addChild(notesNode);
137 //subgraph.addChild(stencilsNode);
138 //subgraph.addChild(limboNode);
139
140 return;
141 } else if(centralNode == outlinesNode) {
142 subgraph.setCentralNode(outlinesNode);
143
144 const vector<Outline*>& outlines = mind->getOutlines();
145 if(outlines.size()) {
146 KnowledgeGraphNode* k;
147 for(Outline* o:outlines) {
148 // TODO: reuse and delete - map<Thing*,Node*>
149 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::OUTLINE, o->getName(), outlinesColor, static_cast<unsigned int>(o->getNotesCount())};
150 k->setThing(o);
151 subgraph.addChild(k);
152 }
153 }
154
155 subgraph.addParent(mindNode);
156
157 return;
158 } else if(centralNode == notesNode) {
159 subgraph.setCentralNode(notesNode);
160
161 // IMPROVE limit maximum number of Ns to be rendered - avoid MF trashing when rendering 1M of nodes
162 vector<Note*> notes{};
163 mind->getAllNotes(notes);
164 if(notes.size()) {
165 KnowledgeGraphNode* k;
166 std::vector<Note*> nc;
167 for(Note* n:notes) {
168 // TODO: reuse and delete - map<Thing*,Node*>
169 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::NOTE, n->getName(), notesColor};
170 k->setThing(n);
171 k->setCardinality(n->getOutline()->getDirectNoteChildrenCount(n));
172 subgraph.addChild(k);
173 }
174 }
175
176 subgraph.addParent(mindNode);
177
178 return;
179 } else if(centralNode == tagsNode) {
180 subgraph.setCentralNode(tagsNode);
181
182 // IMPROVE iterate map, don't load tags
183 map<const Tag*,int> tagsCardinality{};
184 mind->getTagsCardinality(tagsCardinality);
185 KnowledgeGraphNode* n;
186 vector<const Tag*>& tags = mind->getTags().values();
187 for(const Tag* t:tags) {
188 // TODO: reuse and delete - map<Thing*,Node*>
189 n = new KnowledgeGraphNode{KnowledgeGraphNodeType::TAG, t->getName(), t->getColor().asLong(), static_cast<unsigned>(tagsCardinality[t])};
190 subgraph.addChild(n);
191 }
192
193 subgraph.addParent(mindNode);
194
195 return;
196 } else /* if(centralNode == stencilsNode) {
197 subgraph.setCentralNode(stencilsNode);
198
199 subgraph.addParent(mindNode);
200
201 return;
202 } else if(centralNode == limboNode) {
203 subgraph.setCentralNode(limboNode);
204
205 subgraph.addParent(mindNode);
206
207 return;
208 } */
209
210 // things by type
211 if(centralNode->getType() == KnowledgeGraphNodeType::OUTLINE) {
212 subgraph.setCentralNode(centralNode);
213
214 Outline* o = static_cast<Outline*>(centralNode->getThing());
215 KnowledgeGraphNode* k;
216 // child Ns only
217 vector<Note*> children{};
218 o->getDirectNoteChildren(children);
219 for(Note* n:children) {
220 // TODO: reuse and delete - map<Thing*,Node*>
221 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::NOTE, n->getName(), notesColor};
222 k->setThing(n);
223 k->setCardinality(n->getOutline()->getDirectNoteChildrenCount(n));
224 subgraph.addChild(k);
225 }
226
227 const std::vector<const Tag*>* tags = o->getTags();
228 for(const Tag* t:*tags) {
229 // TODO: reuse and delete - map<Thing*,Node*>
230 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::TAG, t->getName(), t->getColor().asLong()};
231 subgraph.addChild(k);
232 }
233
234 subgraph.addParent(outlinesNode);
235
236 return;
237 } else if(centralNode->getType() == KnowledgeGraphNodeType::NOTE) {
238 subgraph.setCentralNode(centralNode);
239
240 Note* n = static_cast<Note*>(centralNode->getThing());
241 KnowledgeGraphNode* k;
242 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::OUTLINE, n->getOutline()->getName(), outlinesColor, static_cast<unsigned int>(n->getOutline()->getNotesCount())};
243 k->setThing(n->getOutline());
244 subgraph.addParent(k);
245
246 // child Ns
247 vector<Note*> children{};
248 n->getOutline()->getDirectNoteChildren(n, children);
249 for(Note* n:children) {
250 // TODO: reuse and delete - map<Thing*,Node*>
251 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::NOTE, n->getName(), notesColor};
252 k->setThing(n);
253 k->setCardinality(n->getOutline()->getDirectNoteChildrenCount(n));
254 subgraph.addChild(k);
255 }
256
257 const std::vector<const Tag*>* tags = n->getTags();
258 for(const Tag* t:*tags) {
259 // TODO: reuse and delete - map<Thing*,Node*>
260 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::TAG, t->getName(), t->getColor().asLong()};
261 subgraph.addChild(k);
262 }
263
264 subgraph.addParent(notesNode);
265
266 return;
267 } else if(centralNode->getType() == KnowledgeGraphNodeType::TAG) {
268 subgraph.setCentralNode(centralNode);
269
270 vector<const Tag*> tags{};
271 tags.push_back(mind->getOntology().findOrCreateTag(centralNode->getName()));
272 // Os
273 vector<Outline*> outlines{};
274 mind->findOutlinesByTags(tags, outlines);
275 if(outlines.size()) {
276 KnowledgeGraphNode* k;
277 for(Outline* o:outlines) {
278 // TODO: reuse and delete - map<Thing*,Node*>
279 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::OUTLINE, o->getName(), outlinesColor, static_cast<unsigned int>(o->getNotesCount())};
280 k->setThing(o);
281 subgraph.addChild(k);
282 }
283 }
284
285 // Ns
286 vector<Note*> notes{};
287 mind->findNotesByTags(tags, notes);
288 if(notes.size()) {
289 KnowledgeGraphNode* k;
290 for(Note* n:notes) {
291 // TODO: reuse and delete - map<Thing*,Node*>
292 k = new KnowledgeGraphNode{KnowledgeGraphNodeType::NOTE, n->getName(), notesColor};
293 k->setThing(n);
294 k->setCardinality(n->getOutline()->getDirectNoteChildrenCount(n));
295 subgraph.addChild(k);
296 }
297 }
298
299 subgraph.addParent(tagsNode);
300
301 return;
302 } /* else if(centralNode->getType() == KnowledgeGraphNodeType::STENCIL) {
303 subgraph.setCentralNode(centralNode);
304
305 subgraph.addParent(stencilsNode);
306
307 return;
308 } */
309 }
310
311 } // m8r namespace
312