View Javadoc

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  		// now, add all possible inflections
73  		for (final VerbInflection.Form form : VerbInflection.Form.values()) {
74  			if (isIchidan && !form.appliesToIchidan()) {
75  				// filter out forms not applicable to ichidan verbs
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 }