Add wadoku pitch dictionary class and allow download
app/src/main/java/eu/lepiller/nani/MainActivity.java
201 | 201 | feedback_text.setText(""); | |
202 | 202 | ||
203 | 203 | ArrayList<Result> searchResult = r.getResults(); | |
204 | - | for(Result result: searchResult) { | |
205 | - | DictionaryFactory.augment(result); | |
206 | - | } | |
207 | 204 | ||
208 | 205 | MojiDetector detector = new MojiDetector(); | |
209 | 206 | String text = r.getText(); |
app/src/main/java/eu/lepiller/nani/dictionary/DictionaryFactory.java
103 | 103 | chooseLanguage(synopsis), | |
104 | 104 | chooseLanguage(description), | |
105 | 105 | cacheDir, url, size, entries, sha256); | |
106 | + | } else if (type.compareTo("wadoku_pitch") == 0) { | |
107 | + | d = new WadokuPitchDictionary(name, | |
108 | + | chooseLanguage(synopsis), | |
109 | + | chooseLanguage(description), | |
110 | + | cacheDir, url, size, entries, sha256); | |
106 | 111 | } else { | |
107 | 112 | continue; | |
108 | 113 | } | |
… | |||
199 | 204 | ArrayList<Result> dr = ((ResultDictionary) d).search(text); | |
200 | 205 | if(dr != null) { | |
201 | 206 | for(Result r: dr) { | |
207 | + | try { | |
208 | + | augment(r); | |
209 | + | } catch (IncompatibleFormatException e) { | |
210 | + | e.printStackTrace(); | |
211 | + | } | |
202 | 212 | String k = r.getKanji(); | |
203 | 213 | if(results.containsKey(k)) { | |
204 | 214 | Result res = results.get(k); | |
… | |||
219 | 229 | return new ArrayList<>(results.values()); | |
220 | 230 | } | |
221 | 231 | ||
222 | - | public static void augment(Result r) { | |
232 | + | private static void augment(Result r) throws IncompatibleFormatException { | |
223 | 233 | for(Dictionary d: dictionaries) { | |
224 | 234 | if(d instanceof ResultAugmenterDictionary && d.isDownloaded()) { | |
225 | 235 | ((ResultAugmenterDictionary) d).augment(r); |
app/src/main/java/eu/lepiller/nani/dictionary/FileDictionary.java
31 | 31 | } | |
32 | 32 | } | |
33 | 33 | ||
34 | + | interface TrieValsDecoder<T> { | |
35 | + | T decodeVals(RandomAccessFile file, long pos) throws IOException; | |
36 | + | } | |
37 | + | ||
34 | 38 | private String mUrl; | |
35 | 39 | private final static String TAG = "FileDictionary"; | |
36 | 40 | ||
… | |||
191 | 195 | } | |
192 | 196 | } | |
193 | 197 | ||
194 | - | private static String getHuffmanString(RandomAccessFile file, Huffman huffman) throws IOException { | |
198 | + | static String getHuffmanString(RandomAccessFile file, Huffman huffman) throws IOException { | |
195 | 199 | StringBuilder b = new StringBuilder(); | |
196 | 200 | ArrayList<Boolean> bits = new ArrayList<>(); | |
197 | 201 | String c = null; | |
… | |||
243 | 247 | } | |
244 | 248 | return results; | |
245 | 249 | } | |
250 | + | ||
251 | + | <T extends Object> T searchTrie(RandomAccessFile file, long triePos, byte[] txt, TrieValsDecoder<T> decoder) throws IOException { | |
252 | + | file.seek(triePos); | |
253 | + | if(txt.length == 0) { | |
254 | + | return decoder.decodeVals(file, triePos); | |
255 | + | } | |
256 | + | ||
257 | + | int valuesLength = file.readShort(); | |
258 | + | Log.d(TAG, "number of values: " + valuesLength); | |
259 | + | file.skipBytes(valuesLength * 4); | |
260 | + | ||
261 | + | int transitionLength = file.readByte(); | |
262 | + | Log.d(TAG, "number of transitions: " + transitionLength); | |
263 | + | ||
264 | + | for(int i = 0; i < transitionLength; i++) { | |
265 | + | byte letter = file.readByte(); | |
266 | + | Log.d(TAG, "Possible transition " + letter + "; Expected transition: " + txt[0]); | |
267 | + | if(letter == txt[0]) { | |
268 | + | Log.d(TAG, "Taking transition "+letter); | |
269 | + | byte[] ntxt = new byte[txt.length-1]; | |
270 | + | System.arraycopy(txt, 1, ntxt, 0, txt.length-1); | |
271 | + | return searchTrie(file, file.readInt(), ntxt, decoder); | |
272 | + | } else { | |
273 | + | file.skipBytes(4); | |
274 | + | } | |
275 | + | } | |
276 | + | ||
277 | + | return null; | |
278 | + | } | |
246 | 279 | } |
app/src/main/java/eu/lepiller/nani/dictionary/ResultAugmenterDictionary.java
9 | 9 | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
10 | 10 | } | |
11 | 11 | ||
12 | - | void augment(Result r) { | |
12 | + | void augment(Result r) throws IncompatibleFormatException { | |
13 | 13 | } | |
14 | 14 | } |
app/src/main/java/eu/lepiller/nani/dictionary/ResultDictionary.java
100 | 100 | } | |
101 | 101 | ||
102 | 102 | private ArrayList<Integer> searchTrie(RandomAccessFile file, long triePos, byte[] txt) throws IOException { | |
103 | - | Log.d(TAG, "searchTrie: " + triePos); | |
104 | - | Log.d(TAG, "Remaining transitions: " + new String(txt, encoding)); | |
105 | - | file.seek(triePos); | |
106 | - | Log.d(TAG, "pointer: " + file.getFilePointer()); | |
107 | - | if(txt.length == 0) { | |
108 | - | return getValues(file, triePos); | |
109 | - | } else { | |
110 | - | int valuesLength = file.readShort(); | |
111 | - | Log.d(TAG, "number of values: " + valuesLength); | |
112 | - | file.skipBytes(valuesLength * 4); | |
113 | - | ||
114 | - | int transitionLength = file.readByte(); | |
115 | - | Log.d(TAG, "number of transitions: " + transitionLength); | |
116 | - | ||
117 | - | for(int i = 0; i < transitionLength; i++) { | |
118 | - | byte letter = file.readByte(); | |
119 | - | Log.d(TAG, "Possible transition " + letter + "; Expected transition: " + txt[0]); | |
120 | - | if(letter == txt[0]) { | |
121 | - | Log.d(TAG, "Taking transition "+letter); | |
122 | - | byte[] ntxt = new byte[txt.length-1]; | |
123 | - | System.arraycopy(txt, 1, ntxt, 0, txt.length-1); | |
124 | - | return searchTrie(file, file.readInt(), ntxt); | |
125 | - | } else { | |
126 | - | file.skipBytes(4); | |
127 | - | } | |
103 | + | return searchTrie(file, triePos, txt, new TrieValsDecoder<ArrayList<Integer>>() { | |
104 | + | @Override | |
105 | + | public ArrayList<Integer> decodeVals(RandomAccessFile file, long pos) throws IOException { | |
106 | + | return getValues(file, pos); | |
128 | 107 | } | |
129 | - | ||
130 | - | return null; | |
131 | - | } | |
108 | + | }); | |
132 | 109 | } | |
133 | 110 | ||
134 | 111 | ArrayList<Result> search(String text) throws IncompatibleFormatException { |
app/src/main/java/eu/lepiller/nani/dictionary/WadokuPitchDictionary.java unknown status 1
1 | + | package eu.lepiller.nani.dictionary; | |
2 | + | ||
3 | + | import android.util.Log; | |
4 | + | ||
5 | + | import java.io.File; | |
6 | + | import java.io.FileNotFoundException; | |
7 | + | import java.io.IOException; | |
8 | + | import java.io.RandomAccessFile; | |
9 | + | import java.util.ArrayList; | |
10 | + | import java.util.Arrays; | |
11 | + | import java.util.List; | |
12 | + | ||
13 | + | import eu.lepiller.nani.R; | |
14 | + | import eu.lepiller.nani.result.Result; | |
15 | + | ||
16 | + | class WadokuPitchDictionary extends ResultAugmenterDictionary { | |
17 | + | private static final String TAG = "PITCH"; | |
18 | + | private Huffman huffman; | |
19 | + | private long triePos; | |
20 | + | ||
21 | + | WadokuPitchDictionary(String name, String description, String fullDescription, File cacheDir, String url, int fileSize, int entries, String hash) { | |
22 | + | super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash); | |
23 | + | } | |
24 | + | ||
25 | + | @Override | |
26 | + | int getDrawableId() { | |
27 | + | return R.drawable.wadoku; | |
28 | + | } | |
29 | + | ||
30 | + | private String findPitch(String kanji, RandomAccessFile file) throws IOException { | |
31 | + | return searchTrie(file, triePos, kanji.getBytes(), new TrieValsDecoder<String>() { | |
32 | + | @Override | |
33 | + | public String decodeVals(RandomAccessFile file, long pos) throws IOException { | |
34 | + | file.seek(pos); | |
35 | + | return getHuffmanString(file, huffman); | |
36 | + | } | |
37 | + | }); | |
38 | + | } | |
39 | + | ||
40 | + | @Override | |
41 | + | void augment(Result r) throws IncompatibleFormatException { | |
42 | + | try { | |
43 | + | RandomAccessFile file = new RandomAccessFile(getFile(), "r"); | |
44 | + | byte[] header = new byte[13]; | |
45 | + | int l = file.read(header); | |
46 | + | if (l != header.length) | |
47 | + | return; | |
48 | + | ||
49 | + | if(!Arrays.equals(header, "NANI_PITCH001".getBytes())) | |
50 | + | throw new IncompatibleFormatException(getName()); | |
51 | + | ||
52 | + | // number of entries | |
53 | + | file.readInt(); | |
54 | + | ||
55 | + | huffman = loadHuffman(file); | |
56 | + | logHuffman(huffman, new ArrayList<Boolean>()); | |
57 | + | ||
58 | + | triePos = file.getFilePointer(); | |
59 | + | ||
60 | + | List<String> kanjis = r.getAlternatives(); | |
61 | + | ||
62 | + | for(String k: kanjis) { | |
63 | + | String pitch = findPitch(k, file); | |
64 | + | if(pitch != null) { | |
65 | + | r.addPitch(k, pitch); | |
66 | + | } | |
67 | + | } | |
68 | + | } catch (FileNotFoundException e) { | |
69 | + | e.printStackTrace(); | |
70 | + | } catch (IOException e) { | |
71 | + | e.printStackTrace(); | |
72 | + | } | |
73 | + | } | |
74 | + | } |
app/src/main/java/eu/lepiller/nani/result/Result.java
2 | 2 | ||
3 | 3 | import android.util.Log; | |
4 | 4 | ||
5 | + | import java.io.IOException; | |
6 | + | import java.io.RandomAccessFile; | |
5 | 7 | import java.util.ArrayList; | |
6 | 8 | import java.util.regex.Matcher; | |
7 | 9 | import java.util.regex.Pattern; | |
… | |||
46 | 48 | } | |
47 | 49 | ||
48 | 50 | public static class Reading { | |
49 | - | private ArrayList<String> kanjis, infos, readings; | |
51 | + | private ArrayList<String> kanjis, infos, readings, pitches; | |
50 | 52 | ||
51 | 53 | public Reading(ArrayList<String> kanjis, ArrayList<String> infos, ArrayList<String> readings) { | |
52 | 54 | this.kanjis = kanjis; | |
53 | 55 | this.infos = infos; | |
54 | 56 | this.readings = readings; | |
57 | + | this.pitches = new ArrayList<>(); | |
58 | + | } | |
59 | + | ||
60 | + | void addPitch(String pitch) { | |
61 | + | pitches.add(pitch); | |
55 | 62 | } | |
56 | 63 | } | |
57 | 64 | ||
… | |||
185 | 192 | // merge senses | |
186 | 193 | senses.addAll(other.senses); | |
187 | 194 | } | |
195 | + | ||
196 | + | public void addPitch(String kanji, String pitch) { | |
197 | + | for(Reading r: readings) { | |
198 | + | if(r.kanjis == null || r.kanjis.size() == 0 || contains(r.kanjis, kanji)) { | |
199 | + | r.addPitch(pitch); | |
200 | + | } | |
201 | + | } | |
202 | + | } | |
203 | + | ||
204 | + | private boolean contains(ArrayList<String> l, String s) { | |
205 | + | for(String c: l) { | |
206 | + | if(c.compareTo(s) == 0) | |
207 | + | return true; | |
208 | + | } | |
209 | + | return false; | |
210 | + | } | |
188 | 211 | } |