1 /***
2 * Aedict - an EDICT browser for Android
3 Copyright (C) 2009 Martin Vysny
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 package sk.baka.aedict.jlptquiz;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Random;
26
27 import sk.baka.aedict.AedictApp;
28 import sk.baka.aedict.R;
29 import sk.baka.aedict.dict.EdictEntry;
30 import sk.baka.aedict.kanji.RomanizationEnum;
31 import sk.baka.aedict.kanji.VerbInflection;
32 import sk.baka.autils.DialogUtils;
33 import android.app.Activity;
34 import android.content.Intent;
35 import android.os.Bundle;
36 import android.view.View;
37 import android.widget.RadioButton;
38 import android.widget.TextView;
39
40 /***
41 * Shows a verb conjugation quiz.
42 *
43 * @author Martin Vysny
44 */
45 public class InflectionQuizActivity extends Activity {
46 public static final String INTENTKEY_ENTRY = "entry";
47
48 public static void launch(final Activity a, final EdictEntry e) {
49 if (!e.isVerb()) {
50 throw new IllegalArgumentException(e + " is not verb");
51 }
52 final Intent i = new Intent(a, InflectionQuizActivity.class);
53 i.putExtra(INTENTKEY_ENTRY, e);
54 a.startActivity(i);
55 }
56
57 private EdictEntry entry;
58 private final Random r = new Random();
59 private int currentQuestion = 0;
60 private int correctAnswer = 0;
61 private boolean showingAnswer = false;
62 private int correctlyAnsweredCount = 0;
63 /***
64 * A list of all possible conjugations. Contains pairs of [conjugated verb
65 * in kanji+kana, english explanation].
66 */
67 private List<String[]> model;
68
69 private void recomputeModel() {
70 model = new ArrayList<String[]>();
71 final boolean isIchidan = entry.isIchidan();
72
73 for (final VerbInflection.Form form : VerbInflection.Form.values()) {
74 if (isIchidan && !form.appliesToIchidan()) {
75
76 continue;
77 }
78 final String inflected = RomanizationEnum.NihonShiki.toHiragana(form.inflect(RomanizationEnum.NihonShiki.toRomaji(entry.reading), isIchidan));
79 final String explanation = getString(form.explanationResId);
80 model.add(new String[] { inflected, explanation });
81 }
82 Collections.shuffle(model);
83 final int questions = Math.min(MAX_NUMBER_OF_QUESTIONS, model.size() / NO_OF_OPTIONS);
84 model = model.subList(0, questions * NO_OF_OPTIONS);
85 currentQuestion = 0;
86 correctAnswer = r.nextInt(NO_OF_OPTIONS);
87 showingAnswer = false;
88 correctlyAnsweredCount = 0;
89 }
90
91 private static final int MAX_NUMBER_OF_QUESTIONS = 10;
92 private static final int NO_OF_OPTIONS = 3;
93
94 @Override
95 protected void onCreate(Bundle savedInstanceState) {
96 super.onCreate(savedInstanceState);
97 setContentView(R.layout.inflection_quiz);
98 entry = (EdictEntry) getIntent().getSerializableExtra(INTENTKEY_ENTRY);
99 recomputeModel();
100 updateGui();
101 findViewById(R.id.next).setOnClickListener(new View.OnClickListener() {
102
103 public void onClick(View v) {
104 if (!showingAnswer) {
105 if (getSelected() == correctAnswer) {
106 correctlyAnsweredCount++;
107 }
108 }
109 showingAnswer = !showingAnswer;
110 if (!showingAnswer) {
111 currentQuestion += NO_OF_OPTIONS;
112 correctAnswer = r.nextInt(NO_OF_OPTIONS);
113 }
114 if (currentQuestion >= model.size()) {
115 findViewById(R.id.next).setEnabled(false);
116 new DialogUtils(InflectionQuizActivity.this).showInfoDialog(getString(R.string.results), AedictApp.format(R.string.youScored, correctlyAnsweredCount, model.size() / NO_OF_OPTIONS));
117 } else {
118 updateGui();
119 }
120 }
121 });
122 }
123
124 private void updateGui() {
125 final String[] answers = new String[NO_OF_OPTIONS];
126 for (int i = 0; i < NO_OF_OPTIONS; i++) {
127 answers[i] = model.get(i + currentQuestion)[1];
128 }
129 final String tmp = answers[correctAnswer];
130 answers[correctAnswer] = answers[0];
131 answers[0] = tmp;
132 ((TextView) findViewById(R.id.question)).setText(model.get(currentQuestion)[0]);
133 for (final Map.Entry<Integer, Integer> e : OPTION_TO_ID.entrySet()) {
134 final RadioButton btn = (RadioButton) findViewById(e.getValue());
135 btn.setEnabled(showingAnswer ? e.getKey() == correctAnswer : true);
136 btn.setText(answers[e.getKey()]);
137 }
138 if (!showingAnswer) {
139 final RadioButton btn = (RadioButton) findViewById(R.id.option1);
140 btn.setChecked(true);
141 }
142 }
143
144 private static final Map<Integer, Integer> OPTION_TO_ID = new HashMap<Integer, Integer>();
145 static {
146 OPTION_TO_ID.put(0, R.id.option1);
147 OPTION_TO_ID.put(1, R.id.option2);
148 OPTION_TO_ID.put(2, R.id.option3);
149 }
150
151 private int getSelected() {
152 for (final Map.Entry<Integer, Integer> e : OPTION_TO_ID.entrySet()) {
153 final RadioButton btn = (RadioButton) findViewById(e.getValue());
154 if (btn.isChecked()) {
155 return e.getKey();
156 }
157 }
158 throw new AssertionError();
159 }
160 }