Add wadoku pitch dictionary class and allow download

Julien LepillerThu Jun 11 04:20:23+0200 2020

23aa3e2

Add wadoku pitch dictionary class and allow download

app/src/main/java/eu/lepiller/nani/MainActivity.java

201201
        feedback_text.setText("");
202202
203203
        ArrayList<Result> searchResult = r.getResults();
204-
        for(Result result: searchResult) {
205-
            DictionaryFactory.augment(result);
206-
        }
207204
208205
        MojiDetector detector = new MojiDetector();
209206
        String text = r.getText();

app/src/main/java/eu/lepiller/nani/dictionary/DictionaryFactory.java

103103
                                    chooseLanguage(synopsis),
104104
                                    chooseLanguage(description),
105105
                                    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);
106111
                        } else {
107112
                            continue;
108113
                        }

199204
                ArrayList<Result> dr = ((ResultDictionary) d).search(text);
200205
                if(dr != null) {
201206
                    for(Result r: dr) {
207+
                        try {
208+
                            augment(r);
209+
                        } catch (IncompatibleFormatException e) {
210+
                            e.printStackTrace();
211+
                        }
202212
                        String k = r.getKanji();
203213
                        if(results.containsKey(k)) {
204214
                            Result res = results.get(k);

219229
        return new ArrayList<>(results.values());
220230
    }
221231
222-
    public static void augment(Result r) {
232+
    private static void augment(Result r) throws IncompatibleFormatException {
223233
        for(Dictionary d: dictionaries) {
224234
            if(d instanceof ResultAugmenterDictionary && d.isDownloaded()) {
225235
                ((ResultAugmenterDictionary) d).augment(r);

app/src/main/java/eu/lepiller/nani/dictionary/FileDictionary.java

3131
        }
3232
    }
3333
34+
    interface TrieValsDecoder<T> {
35+
        T decodeVals(RandomAccessFile file, long pos) throws IOException;
36+
    }
37+
3438
    private String mUrl;
3539
    private final static String TAG = "FileDictionary";
3640

191195
        }
192196
    }
193197
194-
    private static String getHuffmanString(RandomAccessFile file, Huffman huffman) throws IOException {
198+
    static String getHuffmanString(RandomAccessFile file, Huffman huffman) throws IOException {
195199
        StringBuilder b = new StringBuilder();
196200
        ArrayList<Boolean> bits = new ArrayList<>();
197201
        String c = null;

243247
        }
244248
        return results;
245249
    }
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+
    }
246279
}

app/src/main/java/eu/lepiller/nani/dictionary/ResultAugmenterDictionary.java

99
        super(name, description, fullDescription, cacheDir, url, fileSize, entries, hash);
1010
    }
1111
12-
    void augment(Result r) {
12+
    void augment(Result r) throws IncompatibleFormatException {
1313
    }
1414
}

app/src/main/java/eu/lepiller/nani/dictionary/ResultDictionary.java

100100
    }
101101
102102
    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);
128107
            }
129-
130-
            return null;
131-
        }
108+
        });
132109
    }
133110
134111
    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

22
33
import android.util.Log;
44
5+
import java.io.IOException;
6+
import java.io.RandomAccessFile;
57
import java.util.ArrayList;
68
import java.util.regex.Matcher;
79
import java.util.regex.Pattern;

4648
    }
4749
4850
    public static class Reading {
49-
        private ArrayList<String> kanjis, infos, readings;
51+
        private ArrayList<String> kanjis, infos, readings, pitches;
5052
5153
        public Reading(ArrayList<String> kanjis, ArrayList<String> infos, ArrayList<String> readings) {
5254
            this.kanjis = kanjis;
5355
            this.infos = infos;
5456
            this.readings = readings;
57+
            this.pitches = new ArrayList<>();
58+
        }
59+
60+
        void addPitch(String pitch) {
61+
            pitches.add(pitch);
5562
        }
5663
    }
5764

185192
        // merge senses
186193
        senses.addAll(other.senses);
187194
    }
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+
    }
188211
}