;; 普通话发音练习软件 (pflr)
;; Time-stamp: <2009.10.05., 12:25:28 (salvi)>

(defvar *pflr-cedict-buffer* nil
  "The buffer the dictionary is loaded into.")

(defun pflr-load-file (&optional fname)
  "Load the dictionary into a buffer."
  (unless fname
    (setf fname "~/share/emacs/cedict.gb"))
  (if (file-exists-p fname)
      (let ((coding-system-for-read 'gb2312))
        (setq *pflr-cedict-buffer* (find-file-noselect fname)))
    (error "Cannot find file: %s" fname)))

(defun pflr-next-line ()
  "Returns a random line from the CEDICT buffer."
  (save-excursion
    (set-buffer *pflr-cedict-buffer*)
    (goto-line (1+ (random (count-lines 1 (point-max)))))
    (beginning-of-line)
    (if (char-equal (char-after) ?#)
        (next-line)
      (let ((start (point)))
        (end-of-line)
        (buffer-substring start (point))))))

(defun pflr-decompose (str)
  (string-match "^\\([^[]*\\)\\[\\([^]]*\\)\\]\\(.*\\)$" str)
  (list (substring str (match-beginning 1) (match-end 1))
        (substring str (match-beginning 2) (match-end 2))
        (substring str (match-beginning 3) (match-end 3))))

(defun message-read (str)
  (read-input (concat str " ")))

(defmacro pflr-test (name docstr question answer)
  (flet ((word-i (i) `(elt word ,i)))
    `(defun ,name (&optional fname) ,docstr
       (interactive)
       (pflr-load-file fname)
       (message-read "Press C-g to quit, RET to advance.")
       (random t)
       (while t
         (let ((word (pflr-decompose (pflr-next-line))))
           (message-read (concat ,@(mapcar #'word-i question)))
           (message-read (concat ,@(mapcar #'word-i question)
                                 " -> "
                                 ,@(mapcar #'word-i answer))))))))

(pflr-test pflr "Chinese pronounciation training." (0 2) (1))
(pflr-test pflr-hanzi "Chinese character training." (1 2) (0))
(pflr-test pflr-both "Chinese pronounciation and hanzi training." (2) (0 1))