jlpt 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.ja.md +1 -1
- data/lib/jlpt/analyzers/onomatopeia.rb +13 -1
- data/lib/jlpt/analyzers/pitch_accent.rb +25 -11
- data/lib/jlpt/analyzers/simplifier.rb +19 -13
- data/lib/jlpt/core/kanji_details.rb +40 -16
- data/lib/jlpt/data/kanji_details.json +18785 -0
- data/lib/jlpt/data/pitch_accent.json +574 -0
- data/lib/jlpt/data/simplifications.json +638 -0
- data/lib/jlpt/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 589a9e7366fdbd813dda518ecf956168a94fe5290784dee57f2e675e97ca536f
|
|
4
|
+
data.tar.gz: 6cce29bc0a1388f9304f6423670d7513a061b053c1a144e59d85cf565c6ab4ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b7931f4110fe6090c93843a0c594d764d01c7f854bdd661aa3ab23daac4e38e5da9525d15960256e454fd6fa1f22269700bd6ff92ded603f2c4535acda223f37
|
|
7
|
+
data.tar.gz: 6d450ed73830940157be8354f95a38060e1a502ad441c5d04f4f4d884d1f9549fd192f4bd1ef0f4f89d1f7815afe50788f65b722dec71d3a83b10aaa6f8abcaf
|
data/README.ja.md
CHANGED
|
@@ -9,9 +9,15 @@ module JLPT
|
|
|
9
9
|
ONOMATOPOEIA_PATTERNS = %w[
|
|
10
10
|
どきどき わくわく ぺらぺら にこにこ ふわふわ ぎっしり
|
|
11
11
|
ギリギリ イライラ キラキラ ドキドキ ニコニコ ペラペラ
|
|
12
|
-
もちもち すらすら どんどん だんだん いろいろ
|
|
12
|
+
もちもち すらすら どんどん だんだん いろいろ ぴったり
|
|
13
|
+
すっきり さっぱり のんびり うっとり がっかり しっかり
|
|
14
|
+
はっきり こっそり ゆっくり びっくり ばっちり めっきり
|
|
15
|
+
うろうろ ぶらぶら ごちゃごちゃ そわそわ すやすや ぐっすり
|
|
13
16
|
].freeze
|
|
14
17
|
|
|
18
|
+
# Regex for 2-mora repeated reduplicated patterns (ABAB)
|
|
19
|
+
REDUPLICATED_REGEX = /^(\p{Hiragana}{2}|\p{Katakana}{2})\1$/.freeze
|
|
20
|
+
|
|
15
21
|
class << self
|
|
16
22
|
# Extract onomatopoeia words from Japanese text
|
|
17
23
|
#
|
|
@@ -22,6 +28,12 @@ module JLPT
|
|
|
22
28
|
return [] if cleaned.empty?
|
|
23
29
|
|
|
24
30
|
matches = ONOMATOPOEIA_PATTERNS.select { |word| cleaned.include?(word) }
|
|
31
|
+
morphemes = Tokenizer.lemmata(cleaned)
|
|
32
|
+
|
|
33
|
+
morphemes.each do |m|
|
|
34
|
+
matches << m if m.match?(REDUPLICATED_REGEX) && m.length == 4
|
|
35
|
+
end
|
|
36
|
+
|
|
25
37
|
matches.uniq
|
|
26
38
|
end
|
|
27
39
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
3
5
|
module JLPT
|
|
4
6
|
# Pitch Accent Profiler and Pattern Lookup.
|
|
5
7
|
#
|
|
@@ -7,16 +9,9 @@ module JLPT
|
|
|
7
9
|
# for Japanese vocabulary words.
|
|
8
10
|
#
|
|
9
11
|
module PitchAccent
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
'私' => { type: :heiban, pattern: 0 },
|
|
14
|
-
'日本' => { type: :atamadaka, pattern: 1 },
|
|
15
|
-
'猫' => { type: :atamadaka, pattern: 1 },
|
|
16
|
-
'犬' => { type: :atamadaka, pattern: 2 },
|
|
17
|
-
'本' => { type: :atamadaka, pattern: 1 },
|
|
18
|
-
'先生' => { type: :nakadaka, pattern: 3 }
|
|
19
|
-
}.freeze
|
|
12
|
+
DATA_PATH = File.expand_path('../data/pitch_accent.json', __dir__)
|
|
13
|
+
MUTEX = Mutex.new
|
|
14
|
+
@dataset = nil
|
|
20
15
|
|
|
21
16
|
class << self
|
|
22
17
|
# Lookup pitch accent for a vocabulary word
|
|
@@ -26,7 +21,14 @@ module JLPT
|
|
|
26
21
|
def accent_for(word)
|
|
27
22
|
return nil if word.nil? || word.to_s.strip.empty?
|
|
28
23
|
|
|
29
|
-
|
|
24
|
+
w = word.to_s.strip
|
|
25
|
+
dataset = load_dataset!
|
|
26
|
+
|
|
27
|
+
if dataset.key?(w)
|
|
28
|
+
{ type: dataset[w]['type'].to_sym, pattern: dataset[w]['pattern'] }
|
|
29
|
+
else
|
|
30
|
+
{ type: :heiban, pattern: 0 }
|
|
31
|
+
end
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
# Profile pitch accent patterns in Japanese text
|
|
@@ -46,6 +48,18 @@ module JLPT
|
|
|
46
48
|
end
|
|
47
49
|
result
|
|
48
50
|
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def load_dataset!
|
|
55
|
+
return @dataset if @dataset
|
|
56
|
+
|
|
57
|
+
MUTEX.synchronize do
|
|
58
|
+
return @dataset if @dataset
|
|
59
|
+
|
|
60
|
+
@dataset = File.exist?(DATA_PATH) ? JSON.parse(File.read(DATA_PATH)) : {}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
49
63
|
end
|
|
50
64
|
end
|
|
51
65
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
3
5
|
module JLPT
|
|
4
6
|
# Text Simplifier and Beginner Synonym Recommender.
|
|
5
7
|
#
|
|
@@ -7,16 +9,9 @@ module JLPT
|
|
|
7
9
|
# N5/N4/N3 synonym alternatives for Japanese language learners.
|
|
8
10
|
#
|
|
9
11
|
module Simplifier
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
'未曽有' => { reading: 'みぞう', suggestions: %w[今までにない 初めての] },
|
|
14
|
-
'浸透' => { reading: 'しんとう', suggestions: %w[広がる 伝わる] },
|
|
15
|
-
'阻害' => { reading: 'そがい', suggestions: %w[邪魔する 妨げる] },
|
|
16
|
-
'急速' => { reading: 'きゅうそく', suggestions: %w[とても速い 急に] },
|
|
17
|
-
'懸念' => { reading: 'けねん', suggestions: %w[心配 不安] },
|
|
18
|
-
'普及' => { reading: 'ふきゅう', suggestions: %w[広まる みんなが使う] }
|
|
19
|
-
}.freeze
|
|
12
|
+
DATA_PATH = File.expand_path('../data/simplifications.json', __dir__)
|
|
13
|
+
MUTEX = Mutex.new
|
|
14
|
+
@dataset = nil
|
|
20
15
|
|
|
21
16
|
class << self
|
|
22
17
|
# Analyze text and return simplification suggestions for high-level words
|
|
@@ -27,7 +22,8 @@ module JLPT
|
|
|
27
22
|
cleaned = Preprocessor.clean(text)
|
|
28
23
|
return [] if cleaned.empty?
|
|
29
24
|
|
|
30
|
-
|
|
25
|
+
dataset = load_dataset!
|
|
26
|
+
dataset.filter_map do |word, data|
|
|
31
27
|
build_suggestion(word, data) if cleaned.include?(word)
|
|
32
28
|
end
|
|
33
29
|
end
|
|
@@ -39,10 +35,20 @@ module JLPT
|
|
|
39
35
|
{
|
|
40
36
|
word: word,
|
|
41
37
|
level: level,
|
|
42
|
-
reading: data[
|
|
43
|
-
suggestions: data[
|
|
38
|
+
reading: data['reading'],
|
|
39
|
+
suggestions: data['suggestions']
|
|
44
40
|
}
|
|
45
41
|
end
|
|
42
|
+
|
|
43
|
+
def load_dataset!
|
|
44
|
+
return @dataset if @dataset
|
|
45
|
+
|
|
46
|
+
MUTEX.synchronize do
|
|
47
|
+
return @dataset if @dataset
|
|
48
|
+
|
|
49
|
+
@dataset = File.exist?(DATA_PATH) ? JSON.parse(File.read(DATA_PATH)) : {}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
46
52
|
end
|
|
47
53
|
end
|
|
48
54
|
end
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
3
5
|
module JLPT
|
|
4
6
|
# Kanji Details Inspector.
|
|
5
7
|
#
|
|
6
|
-
# Provides stroke count, radical, On'yomi, Kun'yomi,
|
|
8
|
+
# Provides stroke count, radical, On'yomi, Kun'yomi, and JLPT levels for Kanji.
|
|
7
9
|
#
|
|
8
10
|
module KanjiDetails
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'校' => { character: '校', strokes: 10, radical: '木', onyomi: %w[コウ], kunyomi: [], level: :n5 },
|
|
13
|
-
'日' => { character: '日', strokes: 4, radical: '日', onyomi: %w[ニチ], kunyomi: %w[ひ], level: :n5 },
|
|
14
|
-
'本' => { character: '本', strokes: 5, radical: '木', onyomi: %w[ホン], kunyomi: %w[もと], level: :n5 },
|
|
15
|
-
'語' => { character: '語', strokes: 14, radical: '言', onyomi: %w[ゴ], kunyomi: %w[かた.る], level: :n5 },
|
|
16
|
-
'食' => { character: '食', strokes: 9, radical: '食', onyomi: %w[ショク], kunyomi: %w[た.べる], level: :n5 },
|
|
17
|
-
'飲' => { character: '飲', strokes: 12, radical: '食', onyomi: %w[イン], kunyomi: %w[の.む], level: :n5 },
|
|
18
|
-
'行' => { character: '行', strokes: 6, radical: '行', onyomi: %w[コウ], kunyomi: %w[い.く], level: :n5 },
|
|
19
|
-
'来' => { character: '来', strokes: 7, radical: '木', onyomi: %w[ライ], kunyomi: %w[く.る], level: :n5 }
|
|
20
|
-
}.freeze
|
|
11
|
+
DATA_PATH = File.expand_path('../data/kanji_details.json', __dir__)
|
|
12
|
+
MUTEX = Mutex.new
|
|
13
|
+
@dataset = nil
|
|
21
14
|
|
|
22
15
|
class << self
|
|
23
16
|
# Lookup Kanji details for a single character
|
|
@@ -30,8 +23,7 @@ module JLPT
|
|
|
30
23
|
kanji_char = char.to_s.strip[0]
|
|
31
24
|
return nil unless kanji_char.match?(/[\u4E00-\u9FFF]/)
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
KANJI_DATA[kanji_char] || default_kanji_details(kanji_char, level)
|
|
26
|
+
fetch_details(kanji_char)
|
|
35
27
|
end
|
|
36
28
|
|
|
37
29
|
# Get details for all unique kanji in text
|
|
@@ -45,11 +37,43 @@ module JLPT
|
|
|
45
37
|
|
|
46
38
|
private
|
|
47
39
|
|
|
40
|
+
def fetch_details(char)
|
|
41
|
+
dataset = load_dataset!
|
|
42
|
+
level = Dictionary.kanji_level(char) || :out_of_jlpt
|
|
43
|
+
|
|
44
|
+
if dataset.key?(char)
|
|
45
|
+
format_entry(dataset[char])
|
|
46
|
+
else
|
|
47
|
+
default_kanji_details(char, level)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def format_entry(entry)
|
|
52
|
+
{
|
|
53
|
+
character: entry['character'],
|
|
54
|
+
strokes: entry['strokes'],
|
|
55
|
+
radical: entry['radical'],
|
|
56
|
+
onyomi: entry['onyomi'],
|
|
57
|
+
kunyomi: entry['kunyomi'],
|
|
58
|
+
level: entry['level'].to_sym
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def load_dataset!
|
|
63
|
+
return @dataset if @dataset
|
|
64
|
+
|
|
65
|
+
MUTEX.synchronize do
|
|
66
|
+
return @dataset if @dataset
|
|
67
|
+
|
|
68
|
+
@dataset = File.exist?(DATA_PATH) ? JSON.parse(File.read(DATA_PATH)) : {}
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
48
72
|
def default_kanji_details(char, level)
|
|
49
73
|
{
|
|
50
74
|
character: char,
|
|
51
75
|
strokes: 8,
|
|
52
|
-
radical:
|
|
76
|
+
radical: char,
|
|
53
77
|
onyomi: [],
|
|
54
78
|
kunyomi: [],
|
|
55
79
|
level: level
|