diff options
-rw-r--r-- | api/word.ts | 53 | ||||
-rw-r--r-- | core/http/server.ts | 25 | ||||
-rw-r--r-- | core/http/types.ts | 3 | ||||
-rw-r--r-- | db/find.sql | 4 | ||||
-rw-r--r-- | main.ts | 60 |
5 files changed, 98 insertions, 47 deletions
diff --git a/api/word.ts b/api/word.ts index 4dad4a3..4c09cff 100644 --- a/api/word.ts +++ b/api/word.ts @@ -3,9 +3,48 @@ import APIBase from "./base.ts"; import Japanese, { JapaneseFormatter } from "./japanese.ts"; import "../util/string.ts"; -import { TagGroup } from "../search/tags.ts"; +import { Tag, TagGroup, TokenTags } from "../search/tags.ts"; import { SearchWord } from "../search/types.ts"; +// irregular stems taken from <https://en.wikipedia.org/wiki/Japanese_irregular_verbs#suru_and_kuru> +function irregularSuruStem(tags: TokenTags): string { + if (tags.anyOf([ + Tag.Inflection.Polite.Masu, + Tag.Inflection.Suffix.Te, + Tag.Inflection.Tense.Past, + Tag.Inflection.Desirable.Itai, // part of Wikipedia's -ta form + Tag.Inflection.Negative, + Tag.Inflection.Desirable.Volitional, + Tag.Inflection.Command, + ])) return "し"; + if (tags.anyOf([ + Tag.Inflection.Passive, + Tag.Inflection.Causative, + ])) return "さ"; + if (tags.anyOf([ + Tag.Inflection.Potential, + ])) return "でき"; + return "す"; +} + +function irregularKuruStem(tags: TokenTags): string { + if (tags.anyOf([ + Tag.Inflection.Polite.Masu, + Tag.Inflection.Suffix.Te, + Tag.Inflection.Tense.Past, + Tag.Inflection.Desirable.Itai, // part of Wikipedia's -ta form + ])) return "き"; + if (tags.anyOf([ + Tag.Inflection.Negative, + Tag.Inflection.Desirable.Volitional, + Tag.Inflection.Passive, + Tag.Inflection.Causative, + Tag.Inflection.Potential, + Tag.Inflection.Command, + ])) return "こ"; + return "く"; +} + export default class Word extends APIBase { /** @prop dictionary form of verb if this word is a verb */ protected base: Japanese; @@ -29,13 +68,21 @@ export default class Word extends APIBase { input = input as SearchWord; this.base = new Japanese(input.writing, input.reading); if (input.tags.anyOf(TagGroup.Conjugable as string[])) { + // transfer conjugation from input.source to both dictionary reading and writing for furigana var writingCommon = input.writing.cmpLen(input.source); var readingCommon = input.reading.cmpLen(input.source); var stemLength = Math.max(writingCommon, readingCommon); var base = input[writingCommon > readingCommon ? "writing" : "reading"].substring(stemLength); var conjugation = input.source.substring(stemLength); - this.text = new Japanese(input.writing.replaceLast(base, conjugation), - input.reading.replaceLast(base, conjugation)); + + // special reading for irregular verbs + var reading = input.reading; + if (input.writing == '来る') reading = irregularKuruStem(input.tags) + conjugation; + else if (input.writing == '為る') reading = irregularSuruStem(input.tags) + conjugation; + else reading = reading.replaceLast(base, conjugation); + + // generate conjugated version of verb with kanji + this.text = new Japanese(input.writing.replaceLast(base, conjugation), reading); } else { this.text = this.base; } diff --git a/core/http/server.ts b/core/http/server.ts index 7781a22..7e77e19 100644 --- a/core/http/server.ts +++ b/core/http/server.ts @@ -4,21 +4,28 @@ import "../../util/string.ts"; import RawCore from "../raw/api.ts"; import { ConnectionProps, ConnectionPropsDefault } from "./props.ts"; -import { CoreRequest, CoreRequestParseSentence, CoreResponseParseSentence } from "./types.ts"; +import { CoreRequest, CoreRequestSearchSentence, CoreRequestSearchTerms, CoreResponseSearchSentence, CoreResponseSearchTerms } from "./types.ts"; export default class RemoteCoreServer extends RawCore { private props: ConnectionProps; private handlers: Record<string, (req: CoreRequest) => Promise<Response>> = { - parseSentence: async _req => { - var req = _req as CoreRequestParseSentence; - var input = req.options?.input - var options = req.options?.options; - if (!input) return new Response("", { status: 404 }); + "search.terms": async _req => { + var req = _req as CoreRequestSearchTerms; + var term = req.options?.term; + if (!term) return new Response("", { status: 404 }); return new Response(JSON.stringify({ - command: "parseSentence", - response: await this.parseSentence(input, options), - } as CoreResponseParseSentence)); + response: await this.search.terms(term), + } as CoreResponseSearchTerms)); + }, + "search.sentence": async _req => { + var req = _req as CoreRequestSearchSentence; + var sentence = req.options?.sentence + var optional = req.options?.optional; + if (!sentence) return new Response("", { status: 404 }); + return new Response(JSON.stringify({ + response: await this.search.sentence(sentence, optional), + } as CoreResponseSearchSentence)); }, }; diff --git a/core/http/types.ts b/core/http/types.ts index 51c221a..9edc2dc 100644 --- a/core/http/types.ts +++ b/core/http/types.ts @@ -7,7 +7,6 @@ export interface CoreRequest { }; export interface CoreResponse { - command: string; response: any; // final: boolean; }; @@ -21,7 +20,6 @@ export interface CoreRequestSearchSentence extends CoreRequest { }; export interface CoreResponseSearchSentence extends CoreResponse { - command: "search.sentence"; response: SearchSentenceResult; }; @@ -33,6 +31,5 @@ export interface CoreRequestSearchTerms extends CoreRequest { }; export interface CoreResponseSearchTerms extends CoreResponse { - command: "search.terms"; response: Array<SearchTermResult>; }; diff --git a/db/find.sql b/db/find.sql index 6c8a80e..1d31217 100644 --- a/db/find.sql +++ b/db/find.sql @@ -63,8 +63,8 @@ with results(id, expression, reading, tags, depth, rules, original, deinflected) deinflections.term from deinflections inner join term on (term.expression = deinflections.term) or (term.reading = deinflections.term) - inner join term_tag on term_tag.term_id = term.id - inner join tag on term_tag.tag_id = tag.id + left join term_tag on term_tag.term_id = term.id + left join tag on term_tag.tag_id = tag.id group by term.id, deinflections.original, deinflections.rules having term.id is not null ) @@ -1,37 +1,34 @@ -import { ParseResult } from "./language/types.ts"; +import { SearchSentenceResult } from "./search/types.ts"; -function prettyprintParseResult(input: ParseResult) { - for (var token of input.tokens) { +function prettyprintParseResult(input: SearchSentenceResult) { + for (var word of input.words) { var out = ""; - out += token.term_id; + out += word.id; out += ": "; - out += token.writing; + out += word.writing; out += " ("; - out += token.reading; + out += word.reading; out += ") "; - out += token.tags.map(a => `[${a}]`).join(" "); + out += word.tags.map(a => `[${a}]`).join(" "); console.log(out); } - console.log(input.tokens.map(t => t.source).join(" ")); + console.log(input.words.map(t => t.source).join(" ")); } import Core from "./core/api.ts"; import DirectCoreClient from "./core/direct/client.ts"; -import RemoteCoreServer from "./core/http/server.ts"; -import RemoteCoreClient from "./core/http/client.ts"; - async function coreTest(core: Core) { - prettyprintParseResult(await core.parseSentence("浮上したハイラル城の下にてゼルダ様達の捜索を行うこととなった")); + prettyprintParseResult(await core.search.sentence("浮上したハイラル城の下にてゼルダ様達の捜索を行うこととなった")); console.log("-------------"); - prettyprintParseResult(await core.parseSentence("浮上した城の様")); + prettyprintParseResult(await core.search.sentence("浮上した城の様")); console.log("-------------"); - prettyprintParseResult(await core.parseSentence("迷子になってしまった")); + prettyprintParseResult(await core.search.sentence("迷子になってしまった")); console.log("-------------"); - prettyprintParseResult(await core.parseSentence("日本に来て一番驚いたことは自動販売機の多さだ。")); + prettyprintParseResult(await core.search.sentence("日本に来て一番驚いたことは自動販売機の多さだ。")); } // test 1 (direct core) @@ -43,18 +40,21 @@ await (async () => { await coreTest(core); })(); -// console.log("\n".repeat(2)); -// -// // test 2 (remote core) -// await (async () => { -// // default host = localhost:9400 -// new RemoteCoreServer().start(); -// -// var core = new RemoteCoreClient(); -// await core.ready; -// -// console.log("Prepare remote core done"); -// await coreTest(core); -// -// Deno.exit(0); -// })(); +console.log("\n".repeat(2)); + +import RemoteCoreServer from "./core/http/server.ts"; +import RemoteCoreClient from "./core/http/client.ts"; + +// test 2 (remote core) +await (async () => { + // default host = localhost:9400 + new RemoteCoreServer().start(); + + var core = new RemoteCoreClient(); + await core.ready; + + console.log("Prepare remote core done"); + await coreTest(core); + + Deno.exit(0); +})(); |