Add new Dictionary type for radicals

Julien LepillerSat Apr 25 23:55:54+0200 2020

6fc724d

Add new Dictionary type for radicals

app/src/main/java/eu/lepiller/nani/dictionary/RadicalDict.java unknown status 1

1+
package eu.lepiller.nani.dictionary;
2+
3+
import java.io.File;
4+
import java.io.FileNotFoundException;
5+
import java.io.IOException;
6+
import java.io.RandomAccessFile;
7+
import java.util.ArrayList;
8+
import java.util.Arrays;
9+
import java.util.HashMap;
10+
import java.util.HashSet;
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.Set;
14+
15+
import eu.lepiller.nani.R;
16+
17+
public class RadicalDict extends FileDictionary {
18+
    private final Map<String, Integer> strokeCount = new HashMap<>();
19+
    private final Map<String, Integer> radicalStrokeCount = new HashMap<>();
20+
    private final Map<String, String[]> radicals = new HashMap<>();
21+
22+
    final private static String TAG = "RADK";
23+
24+
    @Override
25+
    int getDrawableId() {
26+
        return R.drawable.ic_nani_edrdg;
27+
    }
28+
29+
    @Override
30+
    public void remove() {
31+
        super.remove();
32+
        strokeCount.clear();
33+
        radicalStrokeCount.clear();
34+
        radicals.clear();
35+
    }
36+
    private long fillStrokeCount(RandomAccessFile file) throws IOException{
37+
        int size = file.readShort();
38+
        for(int i=0; i<size; i++) {
39+
            String radical = getString(file);
40+
            int stroke = file.readByte();
41+
42+
            strokeCount.put(radical, stroke);
43+
        }
44+
        return file.getFilePointer();
45+
    }
46+
47+
    private long fillRadicalStrokeCount(RandomAccessFile file) throws IOException {
48+
        int size = file.readShort();
49+
        for(int i=0; i<size; i++) {
50+
            String radical = getString(file);
51+
            int stroke = file.readByte();
52+
53+
            radicalStrokeCount.put(radical, stroke);
54+
        }
55+
        return file.getFilePointer();
56+
    }
57+
58+
    private long fillRadicals(RandomAccessFile file) throws IOException {
59+
        int size = file.readShort();
60+
        for(int i=0; i<size; i++) {
61+
            String radical = getString(file);
62+
            String kanji = getString(file);
63+
64+
            radicals.put(radical, kanji.split(""));
65+
        }
66+
        return file.getFilePointer();
67+
    }
68+
69+
    private void fillTables() throws IncompatibleFormatException {
70+
        try {
71+
            RandomAccessFile file = new RandomAccessFile(getFile(), "r");
72+
            byte[] header = new byte[12];
73+
            int l = file.read(header);
74+
            if (l != header.length)
75+
                return;
76+
77+
            // Check file format version
78+
            if(!Arrays.equals(header, "NANI_RADK001".getBytes()))
79+
                throw new IncompatibleFormatException(getName());
80+
81+
            if (strokeCount.size() == 0) {
82+
                fillRadicals(file);
83+
                fillRadicalStrokeCount(file);
84+
                fillStrokeCount(file);
85+
            }
86+
        } catch (FileNotFoundException e) {
87+
            e.printStackTrace();
88+
        } catch (IOException e) {
89+
            e.printStackTrace();
90+
        }
91+
    }
92+
93+
    RadicalDict(String name, String description, String fullDescription, File cacheDir, String url) {
94+
        super(name, description, fullDescription, cacheDir, url);
95+
    }
96+
97+
    private boolean contains(String[] lst, String s) {
98+
        if(lst==null)
99+
            return false;
100+
        for(String p: lst) {
101+
            if(p.compareTo(s) == 0) {
102+
                return true;
103+
            }
104+
        }
105+
        return false;
106+
    }
107+
108+
    public Map<Integer, List<String>> match(List<String> rad) throws IncompatibleFormatException {
109+
        if(! isDownloaded())
110+
            return null;
111+
112+
        fillTables();
113+
        Map<Integer, List<String>> result = null;
114+
        for(String r: rad) {
115+
            String[] possibilities = radicals.get(r);
116+
            if(possibilities == null)
117+
                continue;
118+
            if(result == null) {
119+
                result = new HashMap<>();
120+
                for(String kanji: possibilities) {
121+
                    Integer strokes = strokeCount.get(kanji);
122+
                    int stroke = 0;
123+
                    if(strokes != null)
124+
                        stroke = strokes;
125+
                    List <String> lst = result.get(stroke);
126+
                    if(lst == null) {
127+
                        lst = new ArrayList<>();
128+
                        result.put(stroke, lst);
129+
                    }
130+
                    lst.add(kanji);
131+
                }
132+
            } else {
133+
                for(List<String> kanjiList: result.values()) {
134+
                    for(String kanji: kanjiList) {
135+
                        if(! contains(possibilities, kanji))
136+
                            kanjiList.remove(kanji);
137+
                    }
138+
                }
139+
            }
140+
        }
141+
        return result;
142+
    }
143+
144+
    public Set<String> availableRadicals(List<String> rad) throws IncompatibleFormatException {
145+
        if(! isDownloaded())
146+
            return null;
147+
148+
        fillTables();
149+
        if(rad.size() == 0)
150+
            return radicals.keySet();
151+
152+
        Set<String> result = new HashSet<>();
153+
        Map<Integer, List<String>> kanjiList = match(rad);
154+
        for(Map.Entry<String, String[]> e: radicals.entrySet()) {
155+
            String radical = e.getKey();
156+
            String[] possibilities = e.getValue();
157+
            boolean possible = false;
158+
            for(List<String> kanjiGroup: kanjiList.values()) {
159+
                if(possible)
160+
                    break;
161+
                for(String s: kanjiGroup) {
162+
                    if(contains(possibilities, s)) {
163+
                        possible = true;
164+
                        break;
165+
                    }
166+
                }
167+
            }
168+
            if(possible)
169+
                result.add(radical);
170+
        }
171+
        return result;
172+
    }
173+
174+
    public Map<Integer, List<String>> getAllRadicals() throws IncompatibleFormatException {
175+
        if(! isDownloaded())
176+
            return null;
177+
178+
        fillTables();
179+
180+
        Map<Integer, List<String>> result = new HashMap<>();
181+
        for(String radical: radicals.keySet()) {
182+
            int stroke = 0;
183+
            Integer strokes = radicalStrokeCount.get(radical);
184+
            if(strokes != null)
185+
                stroke = strokes;
186+
            List<String> rads = result.get(stroke);
187+
            if(rads == null) {
188+
                rads = new ArrayList<>();
189+
                result.put(stroke, rads);
190+
            }
191+
            rads.add(radical);
192+
        }
193+
        return result;
194+
    }
195+
}