diff options
author | Alex Yatskov <alex@foosoft.net> | 2016-12-22 18:50:58 -0800 |
---|---|---|
committer | Alex Yatskov <alex@foosoft.net> | 2016-12-22 18:50:58 -0800 |
commit | 39fa11f72bae62985ee5b27103e5959dab30316c (patch) | |
tree | e7fe89d18a2b0bfa892ede044d7e6dcc076bbf7b /ext/bg/js/translator.js | |
parent | 5710dc55a73491a0be2259fbd21874bddda54877 (diff) | |
parent | 9d21f8a456530c29c7c03db4896562a4902f6f8a (diff) |
Merge branch 'dev'
Diffstat (limited to 'ext/bg/js/translator.js')
-rw-r--r-- | ext/bg/js/translator.js | 199 |
1 files changed, 57 insertions, 142 deletions
diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js index 44f37e31..f29b90c9 100644 --- a/ext/bg/js/translator.js +++ b/ext/bg/js/translator.js @@ -20,96 +20,33 @@ class Translator { constructor() { this.loaded = false; - this.tagMeta = null; - this.dictionary = new Dictionary(); + this.ruleMeta = null; + this.database = new Database(); this.deinflector = new Deinflector(); } - loadData(callback) { + prepare() { if (this.loaded) { return Promise.resolve(); } - return loadJson('bg/data/rules.json').then(rules => { - this.deinflector.setRules(rules); - return loadJson('bg/data/tags.json'); - }).then(tagMeta => { - this.tagMeta = tagMeta; - return this.dictionary.prepareDb(); - }).then(exists => { - if (exists) { - return; - } - - if (callback) { - callback({state: 'begin', progress: 0}); - } - - const banks = {}; - const bankCallback = (loaded, total, indexUrl) => { - banks[indexUrl] = {loaded, total}; - - let percent = 0.0; - for (const url in banks) { - percent += banks[url].loaded / banks[url].total; - } + const promises = [ + loadJsonInt('bg/data/deinflect.json'), + this.database.prepare() + ]; - percent /= 3.0; - - if (callback) { - callback({state: 'update', progress: Math.ceil(100.0 * percent)}); - } - }; - - return Promise.all([ - this.dictionary.importTermDict('bg/data/edict/index.json', bankCallback), - this.dictionary.importTermDict('bg/data/enamdict/index.json', bankCallback), - this.dictionary.importKanjiDict('bg/data/kanjidic/index.json', bankCallback), - ]).then(() => { - return this.dictionary.sealDb(); - }).then(() => { - if (callback) { - callback({state: 'end', progress: 100.0}); - } - }); - }).then(() => { + return Promise.all(promises).then(([reasons]) => { + this.deinflector.setReasons(reasons); this.loaded = true; }); } - findTermGroups(text) { - const deinflectGroups = {}; - const deinflectPromises = []; - - for (let i = text.length; i > 0; --i) { - deinflectPromises.push( - this.deinflector.deinflect(text.slice(0, i), term => { - return this.dictionary.findTerm(term).then(definitions => definitions.map(definition => definition.tags)); - }).then(deinflects => { - const processPromises = []; - for (const deinflect of deinflects) { - processPromises.push(this.processTerm( - deinflectGroups, - deinflect.source, - deinflect.tags, - deinflect.rules, - deinflect.root - )); - } - - return Promise.all(processPromises); - }) - ); - } - - return Promise.all(deinflectPromises).then(() => deinflectGroups); - } - - findTerm(text, enableSoftKatakanaSearch) { - return this.findTermGroups(text).then(groups => { + findTerm(text, dictionaries, enableSoftKatakanaSearch) { + const cache = {}; + return this.findDeinflectionGroups(text, dictionaries, cache).then(groups => { const textHiragana = wanakana._katakanaToHiragana(text); if (text !== textHiragana && enableSoftKatakanaSearch) { - return this.findTermGroups(textHiragana).then(groupsHiragana => { + return this.findDeinflectionGroups(textHiragana, dictionaries, cache).then(groupsHiragana => { for (const key in groupsHiragana) { groups[key] = groups[key] || groupsHiragana[key]; } @@ -137,13 +74,11 @@ class Translator { }); } - findKanji(text) { - const processed = {}; - const promises = []; - + findKanji(text, dictionaries) { + const processed = {}, promises = []; for (const c of text) { if (!processed[c]) { - promises.push(this.dictionary.findKanji(c).then((definitions) => definitions)); + promises.push(this.database.findKanji(c, dictionaries)); processed[c] = true; } } @@ -151,73 +86,53 @@ class Translator { return Promise.all(promises).then(sets => this.processKanji(sets.reduce((a, b) => a.concat(b), []))); } - processTerm(groups, source, tags, rules, root) { - return this.dictionary.findTerm(root).then(definitions => { - for (const definition of definitions) { - if (definition.id in groups) { - continue; - } - - let matched = tags.length === 0; - for (const tag of tags) { - if (definition.tags.includes(tag)) { - matched = true; - break; - } - } - - if (!matched) { - continue; - } - - const tagItems = []; - for (const tag of definition.tags) { - const tagItem = { - name: tag, - class: 'default', - order: Number.MAX_SAFE_INTEGER, - score: 0, - desc: definition.entities[tag] || '', - }; - - applyTagMeta(tagItem, this.tagMeta); - tagItems.push(tagItem); - } - - let score = 0; - for (const tagItem of tagItems) { - score += tagItem.score; - } - - groups[definition.id] = { - score, - source, - rules, - expression: definition.expression, - reading: definition.reading, - glossary: definition.glossary, - tags: sortTags(tagItems) - }; + findDeinflectionGroups(text, dictionaries, cache) { + const definer = term => { + if (cache.hasOwnProperty(term)) { + return Promise.resolve(cache[term]); } - }); + + return this.database.findTerm(term, dictionaries).then(definitions => cache[term] = definitions); + }; + + const groups = {}, promises = []; + for (let i = text.length; i > 0; --i) { + promises.push( + this.deinflector.deinflect(text.slice(0, i), definer).then(deinflections => { + for (const deinflection of deinflections) { + this.processDeinflection(groups, deinflection); + } + }) + ); + } + + return Promise.all(promises).then(() => groups); } - processKanji(definitions) { + processDeinflection(groups, {source, rules, reasons, definitions}, dictionaries) { for (const definition of definitions) { - const tagItems = []; - for (const tag of definition.tags) { - const tagItem = { - name: tag, - class: 'default', - order: Number.MAX_SAFE_INTEGER, - desc: '', - }; - - applyTagMeta(tagItem, this.tagMeta); - tagItems.push(tagItem); + if (definition.id in groups) { + continue; } - definition.tags = sortTags(tagItems); + const tags = definition.tags.map(tag => buildTag(tag, definition.tagMeta)); + groups[definition.id] = { + source, + reasons, + score: definition.score, + dictionary: definition.dictionary, + expression: definition.expression, + reading: definition.reading, + glossary: definition.glossary, + tags: sortTags(tags) + }; + } + } + + processKanji(definitions) { + for (const definition of definitions) { + const tags = definition.tags.map(tag => buildTag(tag, definition.tagMeta)); + definition.tags = sortTags(tags); } return definitions; |