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 | } | |