summaryrefslogtreecommitdiff
path: root/ext/bg/js/translator.js
diff options
context:
space:
mode:
authorAlex Yatskov <alex@foosoft.net>2016-09-18 19:50:32 -0700
committerAlex Yatskov <alex@foosoft.net>2016-09-18 19:50:32 -0700
commitb44d19b35e120133a4bb751e176aec4d14b6cbc5 (patch)
tree05b23ef7e70e57f2cf38584a20c864ff0d7e4853 /ext/bg/js/translator.js
parent7bd642e53868e0a3154b285be969cc2e6068f46f (diff)
parent4e2d7327c5b1aa8eed035dc4c177a3b9b49c5ab7 (diff)
Merge branch 'dev'
Diffstat (limited to 'ext/bg/js/translator.js')
-rw-r--r--ext/bg/js/translator.js294
1 files changed, 151 insertions, 143 deletions
diff --git a/ext/bg/js/translator.js b/ext/bg/js/translator.js
index fd414847..e534e0cb 100644
--- a/ext/bg/js/translator.js
+++ b/ext/bg/js/translator.js
@@ -25,171 +25,199 @@ class Translator {
this.deinflector = new Deinflector();
}
- loadData({loadEnamDict=true}, callback) {
+ loadData(callback) {
if (this.loaded) {
- callback();
- return;
+ return Promise.resolve();
}
- Translator.loadData('bg/data/rules.json')
- .then((response) => {
- this.deinflector.setRules(JSON.parse(response));
- return Translator.loadData('bg/data/tags.json');
- })
- .then((response) => {
- this.tagMeta = JSON.parse(response);
- return Translator.loadData('bg/data/edict.json');
- })
- .then((response) => {
- this.dictionary.addTermDict('edict', JSON.parse(response));
- return Translator.loadData('bg/data/kanjidic.json');
- })
- .then((response) => {
- this.dictionary.addKanjiDict('kanjidic', JSON.parse(response));
- return loadEnamDict ? Translator.loadData('bg/data/enamdict.json') : Promise.resolve(null);
- })
- .then((response) => {
- if (response !== null) {
- this.dictionary.addTermDict('enamdict', JSON.parse(response));
+ 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;
}
- this.loaded = true;
- callback();
- });
- }
+ percent /= 3.0;
- findTerm(text) {
- const groups = {};
- for (let i = text.length; i > 0; --i) {
- const term = text.slice(0, i);
- const dfs = this.deinflector.deinflect(term, t => {
- const tags = [];
- for (const d of this.dictionary.findTerm(t)) {
- tags.push(d.tags);
+ if (callback) {
+ callback({state: 'update', progress: Math.ceil(100.0 * percent)});
}
+ };
- return tags;
+ 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(() => {
+ this.loaded = true;
+ });
+ }
- if (dfs === null) {
- continue;
- }
+ findTermGroups(text) {
+ const deinflectGroups = {};
+ const deinflectPromises = [];
- for (const df of dfs) {
- this.processTerm(groups, df.source, df.tags, df.rules, df.root);
- }
+ 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);
+ })
+ );
}
- let definitions = [];
- for (const key in groups) {
- definitions.push(groups[key]);
- }
+ return Promise.all(deinflectPromises).then(() => deinflectGroups);
+ }
- definitions = definitions.sort((v1, v2) => {
- const sl1 = v1.source.length;
- const sl2 = v2.source.length;
- if (sl1 > sl2) {
- return -1;
- } else if (sl1 < sl2) {
- return 1;
+ findTerm(text) {
+ return this.findTermGroups(text).then(deinflectGroups => {
+ let definitions = [];
+ for (const key in deinflectGroups) {
+ definitions.push(deinflectGroups[key]);
}
- const s1 = v1.score;
- const s2 = v2.score;
- if (s1 > s2) {
- return -1;
- } else if (s1 < s2) {
- return 1;
- }
+ definitions = definitions.sort((v1, v2) => {
+ const sl1 = v1.source.length;
+ const sl2 = v2.source.length;
+ if (sl1 > sl2) {
+ return -1;
+ } else if (sl1 < sl2) {
+ return 1;
+ }
- const rl1 = v1.rules.length;
- const rl2 = v2.rules.length;
- if (rl1 < rl2) {
- return -1;
- } else if (rl1 > rl2) {
- return 1;
- }
+ const s1 = v1.score;
+ const s2 = v2.score;
+ if (s1 > s2) {
+ return -1;
+ } else if (s1 < s2) {
+ return 1;
+ }
- return v2.expression.localeCompare(v1.expression);
- });
+ const rl1 = v1.rules.length;
+ const rl2 = v2.rules.length;
+ if (rl1 < rl2) {
+ return -1;
+ } else if (rl1 > rl2) {
+ return 1;
+ }
- let length = 0;
- for (const result of definitions) {
- length = Math.max(length, result.source.length);
- }
+ return v2.expression.localeCompare(v1.expression);
+ });
+
+ let length = 0;
+ for (const result of definitions) {
+ length = Math.max(length, result.source.length);
+ }
- return {definitions: definitions, length: length};
+ return {definitions, length};
+ });
}
findKanji(text) {
- let definitions = [];
const processed = {};
+ const promises = [];
for (const c of text) {
if (!processed[c]) {
- definitions = definitions.concat(this.dictionary.findKanji(c));
+ promises.push(this.dictionary.findKanji(c).then((definitions) => definitions));
processed[c] = true;
}
}
- return this.processKanji(definitions);
+ return Promise.all(promises).then(sets => this.processKanji(sets.reduce((a, b) => a.concat(b))));
}
processTerm(groups, source, tags, rules, root) {
- for (const entry of this.dictionary.findTerm(root)) {
- if (entry.id in groups) {
- continue;
- }
+ 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 (entry.tags.indexOf(tag) !== -1) {
- matched = true;
- break;
+ let matched = tags.length === 0;
+ for (const tag of tags) {
+ if (definition.tags.includes(tag)) {
+ matched = true;
+ break;
+ }
}
- }
- if (!matched) {
- continue;
- }
+ if (!matched) {
+ continue;
+ }
- const tagItems = [];
- for (const tag of entry.tags) {
- const tagItem = {
- name: tag,
- class: 'default',
- order: Number.MAX_SAFE_INTEGER,
- score: 0,
- desc: entry.entities[tag] || '',
- };
+ 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] || '',
+ };
+
+ this.applyTagMeta(tagItem);
+ tagItems.push(tagItem);
+ }
- this.applyTagMeta(tagItem);
- tagItems.push(tagItem);
- }
+ let score = 0;
+ for (const tagItem of tagItems) {
+ score += tagItem.score;
+ }
- 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: Translator.sortTags(tagItems)
+ };
}
-
- groups[entry.id] = {
- score,
- source,
- rules,
- expression: entry.expression,
- reading: entry.reading,
- glossary: entry.glossary,
- tags: Translator.sortTags(tagItems)
- };
- }
+ });
}
- processKanji(entries) {
- const results = [];
-
- for (const entry of entries) {
+ processKanji(definitions) {
+ for (const definition of definitions) {
const tagItems = [];
- for (const tag of entry.tags) {
+ for (const tag of definition.tags) {
const tagItem = {
name: tag,
class: 'default',
@@ -201,16 +229,10 @@ class Translator {
tagItems.push(tagItem);
}
- results.push({
- character: entry.character,
- kunyomi: entry.kunyomi,
- onyomi: entry.onyomi,
- glossary: entry.glossary,
- tags: Translator.sortTags(tagItems)
- });
+ definition.tags = Translator.sortTags(tagItems);
}
- return results;
+ return definitions;
}
applyTagMeta(tag) {
@@ -241,18 +263,4 @@ class Translator {
return 0;
});
}
-
- static isKanji(c) {
- const code = c.charCodeAt(0);
- return code >= 0x4e00 && code < 0x9fb0 || code >= 0x3400 && code < 0x4dc0;
- }
-
- static loadData(url) {
- return new Promise((resolve, reject) => {
- const xhr = new XMLHttpRequest();
- xhr.addEventListener('load', () => resolve(xhr.responseText));
- xhr.open('GET', chrome.extension.getURL(url), true);
- xhr.send();
- });
- }
}