/* A kana testing applet
 * Copyright (C) 2003 Tim Hurman <kano@kano.org.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class kanaTest extends JApplet implements ItemListener, ActionListener
{
	private kanaQuestion kq;
	private JLabel lState, lTotal;
	private JTextField tAns, tQue;

	/* aux items */
	private JComboBox lFont, lSet;
	private String setItems[] = {"Hiragana", "Katakana", "Both"};
	private String fontList[];
	private Date qstarted, qended;

	/* class constructor */
	public kanaTest () {
		/* initalise the applet */
		super();
		Font f = new Font("Dialog", Font.PLAIN, 14);

		/* get the font list */
        fontList = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

		/* where to add things */
		Container cp = getContentPane();
		cp.setLayout(new GridLayout(5, 2));
		cp.setBackground(Color.white);
	
		/* make the Panel and components */
		cp.add(new JLabel("Glyph:", Label.RIGHT));
		tQue = new JTextField("", 5);
		tQue.setEnabled(false);
		tQue.setFont(f);
		cp.add(tQue);

		cp.add(new JLabel("Sound:", Label.RIGHT));
		tAns = new JTextField("", 5);
		tQue.setFont(f);
		tAns.addActionListener(this);
		cp.add(tAns);

		lState = new JLabel("");
		cp.add(lState);
		lTotal = new JLabel("");
		cp.add(lTotal);

		/* aux items */
		cp.add(new JLabel("Font:"));
		lFont = new JComboBox(fontList);
		lFont.setSelectedItem( "Dialog" );
		lFont.setBackground(Color.white);
		cp.add(lFont);
		lFont.addItemListener(this);

		cp.add(new JLabel("Glyphs:"));
		lSet = new JComboBox(setItems);
		lSet.setSelectedIndex(2);
		lSet.setBackground(Color.white);
		cp.add(lSet);
		lSet.addItemListener(this);

		kq = new kanaQuestion();
	}

	/* applet loaded */
	public void init() {
		lTotal.setText(kq.getScore());
		kq.makeQuestions(lSet.getSelectedIndex());
		tQue.setText(kq.getNewQuestion());
		qstarted = new Date();
	}

	/* browser exited */
	public void destroy() {
	}

	/* user entered page */
	public void start() {
	}

	/* user left page */
	public void stop() {
	}

	/* the event listener */
	public void itemStateChanged(ItemEvent e) {
		if (e.getStateChange() != ItemEvent.SELECTED)
			return;

		if (e.getSource() == lSet) {
			kq.makeQuestions(lSet.getSelectedIndex());
		}
		if (e.getSource() == lFont) {
			Font f = new Font((String)e.getItem(), Font.PLAIN, 14);
			tAns.setFont(f);
			tQue.setFont(f);
		}
	}
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == tAns) {
			qended = new Date();
			if(kq.checkAnswer(tAns.getText(),
			  (int)(qended.getTime() - qstarted.getTime())/1000)) {
				/* correct answer */
				lState.setForeground(Color.green);
				lState.setText("Correct");
			} else {
				lState.setForeground(Color.red);
				lState.setText("Incorrect (" + kq.getRealAnswer() + ")");
			}
			lTotal.setText(kq.getScore());
			tQue.setText(kq.getNewQuestion());
			tAns.setText("");
			qstarted = new Date();
		}
	}

	/* application */
	public static void main(String args[]) {
		Frame f = new Frame("kanaTest");
		kanaTest kt = new kanaTest();

		kt.init();
		kt.start();

		f.addWindowListener(
			new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					System.exit(0);
				}
			}
		);

		f.add("Center", kt);
		f.pack();
		f.show();
    }


}

/* the score question decider + scorekeeper */
class kanaQuestion
{
	private String hiragana[] = {
		"あ", "い", "う", "え", "お",
		"か", "き", "く", "け", "こ",
		"さ", "し", "す", "せ", "そ",
		"た", "ち", "つ", "て", "と",
		"な", "に", "ぬ", "ね", "の",
		"は", "ひ", "ふ", "へ", "ほ",
		"ま", "み", "む", "め", "も",
		"や",       "ゆ",       "よ",
		"ら", "り", "る", "れ", "ろ",
		"わ",                   "を",
		"ん",
		"が", "ぎ", "ぐ", "げ", "ご",
		"ざ", "じ", "ず", "ぜ", "ぞ",
		"だ", "ぢ", "づ", "で", "ど",
		"ば", "び", "ぶ", "べ", "ぼ",
		"ぱ", "ぴ", "ぷ", "ぺ", "ぽ"
	};
	private String katakana[] = {
		"ア", "イ", "ウ", "エ", "オ",
		"カ", "キ", "ク", "ケ", "コ",
		"サ", "シ", "ス", "セ", "ソ",
		"タ", "チ", "ツ", "テ", "ト",
		"ナ", "ニ", "ヌ", "ネ", "ノ",
		"ハ", "ヒ", "フ", "ヘ", "ホ",
		"マ", "ミ", "ム", "メ", "モ",
		"ヤ",       "ユ",       "ヨ",
		"ラ", "リ", "ル", "レ", "ロ",
		"ワ",                   "ヲ",
		"ン",
		"ガ", "ギ", "グ", "ゲ", "ゴ",
		"ザ", "ジ", "ズ", "ゼ", "ゾ",
		"ダ", "ヂ", "ヅ", "デ", "ド",
		"バ", "ビ", "ブ", "ベ", "ボ",
		"パ", "ピ", "プ", "ペ", "ポ"
	};
	private String romanji[] = {
		"a",  "i",   "u",   "e",  "o",
		"ka", "ki",  "ku",  "ke", "ko",
		"sa", "shi", "su",  "se", "so",
		"ta", "chi", "tsu", "te", "to",
		"na", "ni",  "nu",  "ne", "no",
		"ha", "hi",  "fu",  "he", "ho",
		"ma", "mi",  "mu",  "me", "mo",
		"ya",        "yu",        "yo",
		"ra", "ri",  "ru",  "re", "ro",
		"wa",                     "o",
		"n",
		"ga", "gi",  "gu",  "ge", "go",
		"za", "ji",  "zu",  "ze", "zo",
		"da", "ji",  "zu",  "de", "do",
		"ba", "bi",  "bu",  "be", "bo",
		"pa", "pi",  "pu",  "pe", "po"
	};

	private String questions[];
	private String answers[];
	private int scores[];
	private Random rand;
	private int total, correct;
	private String prev_question;
	private int this_question;

	public kanaQuestion() {
			rand = new Random(new Date().getTime());
			total = correct = 0;
			this_question = 0;
			prev_question = "";
	}

	/* make and initalise the questions list */
	public void makeQuestions(int selection) {
		int i;

		/* decide which questions to pose */
		if (0 == selection) { /* hiragana only */
			questions = new String[hiragana.length];
			answers = new String[hiragana.length];
			scores = new int[hiragana.length];
			for (i=0; i<hiragana.length; i++) {
				questions[i] = hiragana[i];
				answers[i] = romanji[i];
				scores[i] = rand.nextInt();
			}
		} else if (1 == selection) { /* katakana only */
			questions = new String[katakana.length];
			answers = new String[katakana.length];
			scores = new int[katakana.length];
			for (i=0; i<katakana.length; i++) {
				questions[i] = katakana[i];
				answers[i] = romanji[i];
				scores[i] = rand.nextInt();
			}
		} else if (2 == selection) { /* hiragana and katakana */
			questions = new String[hiragana.length+katakana.length];
			answers = new String[hiragana.length+katakana.length];
			scores = new int[hiragana.length+katakana.length];
			for (i=0; i<hiragana.length; i++) {
				questions[i] = hiragana[i];
				answers[i] = romanji[i];
				scores[i] = rand.nextInt();
			}
			for (i=0; i<katakana.length; i++) {
				questions[i+hiragana.length] = katakana[i];
				answers[i+hiragana.length] = romanji[i];
				scores[i+hiragana.length] = rand.nextInt();
			}
		}

		/* sort the questions */
		bubbleSort();
		for (i=0; i<scores.length; i++) {
			scores[i] = 0;
		}
	}

	/* sort the questions and answers array */
	private void bubbleSort() {
		int i, tmps;
		String tmpq, tmpa;
		boolean changed=true;

		while (changed) {
			for (i=1, changed=false; i<scores.length; i++) {
				if (scores[i-1] > scores[i]) { /* swap */
					tmpq = questions[i-1];
					tmpa = answers[i-1];
					tmps = scores[i-1];

					questions[i-1] = questions[i];
					answers[i-1] = answers[i];
					scores[i-1] = scores[i];

					questions[i] = tmpq;
					answers[i] = tmpa;
					scores[i] = tmps;
					changed = true;
				}
			}
			/* done for loop */
		}
		/* done while loop */
	}


	/* get a new question, but not the one that was just asked */
	public String getNewQuestion() {
		prev_question = questions[this_question];
		bubbleSort();

		while (true) {
			this_question = rand.nextInt(5);
			if (0 != prev_question.compareTo(questions[this_question]))
				break;
		}

		return questions[this_question];
	}

	/* check the users answer */
	public boolean checkAnswer(String user_answer, int seconds) {
		total++;
		if (0 == user_answer.compareTo(answers[this_question])) {
			correct++;
			if (seconds == 0) {
				scores[this_question] += 10;
			} else if (seconds > 9) {
				scores[this_question] += 1;
			} else {
				scores[this_question] += 10 - seconds;
			}
			return true;
		}

		/* incorrect */
		return false;
	}

	/* return the real answer if asked */
	public String getRealAnswer() {
		return answers[this_question];
	}

	/* get the score as a string */
	public String getScore() {
		return Integer.toString(correct) + "/" + Integer.toString(total);
	}
}

