@@ -66,10 +66,14 @@ export class KanjiNode {
66
66
//---------------------------------------------------------------------
67
67
// FUNCTIONS TO CREATE THE GRAPH
68
68
69
- function findOrCreateNode ( name : string , thelist : KanjiNode [ ] ) : KanjiNode {
69
+ function findOrCreateNode ( name : string , thelist : KanjiNode [ ] , properties ?: KanjiNode ) : KanjiNode {
70
70
let node = thelist . find ( x => x . name === name ) ;
71
71
if ( ! node ) {
72
- node = new KanjiNode ( name ) ;
72
+ if ( properties ) {
73
+ node = properties . shallowCopy ( ) ;
74
+ } else {
75
+ node = new KanjiNode ( name ) ;
76
+ }
73
77
thelist . push ( node ) ;
74
78
}
75
79
return node ;
@@ -99,6 +103,7 @@ function buildDAG(): [KanjiNode[], KanjiNode] {
99
103
}
100
104
101
105
// New subgraph functions
106
+
102
107
/**
103
108
* This function takes the whole kanji topography as graph and node list and returns a subgraph of kanjis to know.
104
109
* The subgraph is a DAG with the same structure as the original, but with only the relevant nodes.
@@ -128,22 +133,24 @@ function getTargetSubgraph(allRoot: KanjiNode, nodeList: KanjiNode[], targetKanj
128
133
}
129
134
130
135
// Step 2: create a new graph with only the relevant nodes
131
- const relevantWalker = ( node : KanjiNode ) : KanjiNode => {
136
+ const relevantWalker = ( startNode : KanjiNode , foundList : KanjiNode [ ] ) : KanjiNode => {
132
137
// copy the node properties
133
- const currentNewNode = node . shallowCopy ( ) ;
138
+ // debugger;
139
+ const currentNewNode = findOrCreateNode ( startNode . name , foundList , startNode ) ;
134
140
135
141
// add only the relevant parents
136
- for ( const child of node . children ) {
142
+ for ( const child of startNode . children ) {
137
143
if ( child . isRelevant ) {
138
- const relevantChildrenRoot = relevantWalker ( child ) ;
144
+ const relevantChildrenRoot = relevantWalker ( child , foundList ) ;
139
145
currentNewNode . addChild ( relevantChildrenRoot ) ;
140
146
relevantChildrenRoot . addParent ( currentNewNode ) ;
141
147
}
142
148
}
143
149
144
150
return currentNewNode
145
151
}
146
- const relevantRootNode = relevantWalker ( allRoot ) ;
152
+ const relevantKanji : KanjiNode [ ] = [ ] ;
153
+ const relevantRootNode = relevantWalker ( allRoot , relevantKanji ) ;
147
154
148
155
// Step 2a: clean up the big graph
149
156
for ( const node of nodeList ) {
@@ -209,6 +216,23 @@ function markKnown(rootNode: KanjiNode, knownList: string[]) {
209
216
// ---------------------------------------------------------------------
210
217
// Order Recommendation
211
218
219
+ // This function could be used to check if all parents of a node are in the list, but
220
+ // it is not used since I instead check on insert time.
221
+ // function isReachable(target: KanjiNode, included: KanjiNode[]): boolean {
222
+ // // Special case: if the target is a root, it is always reachable
223
+ // if (target.parents.length === 0) {
224
+ // return true;
225
+ // }
226
+
227
+ // // Node is reachable if all parents are included
228
+ // for (const parent of target.parents) {
229
+ // if (!included.includes(parent)) {
230
+ // return false;
231
+ // }
232
+ // }
233
+ // return true;
234
+ // }
235
+
212
236
/**
213
237
* Generates an order to study the kanji, where
214
238
* 1. Consitituating parts are always learned before the kanji that uses them
@@ -227,7 +251,6 @@ export function getRecommendedOrder(rootNode: KanjiNode): KanjiNode[] {
227
251
228
252
while ( possibleCandidates . length > 0 ) {
229
253
const candidate = possibleCandidates . shift ( ) ;
230
-
231
254
// This should never happen but the compiler wants this line
232
255
if ( ! candidate ) throw new Error ( "unexpectedly didn't receive a candidate" ) ;
233
256
@@ -263,7 +286,6 @@ export function getRecommendedOrder(rootNode: KanjiNode): KanjiNode[] {
263
286
return ( a . priority || 0 ) - ( b . priority || 0 ) ;
264
287
} ) ;
265
288
}
266
-
267
289
return returnList ;
268
290
}
269
291
0 commit comments