157 lines
5.8 KiB
EmacsLisp
157 lines
5.8 KiB
EmacsLisp
;;; 06-linuxplus-quiz-mode.el --- linuxplus-quiz-mode
|
|
|
|
(defvar-local linuxplus-quiz-questions nil
|
|
"Questions for the current Linux+ quiz buffer.")
|
|
|
|
(defvar-local linuxplus-quiz-answers nil
|
|
"Correct answers for the current Linux+ quiz buffer.")
|
|
|
|
(defvar-local linuxplus-quiz-user-answers nil
|
|
"User answers for the current Linux+ quiz buffer.")
|
|
|
|
(defvar-local linuxplus-quiz-current-index 0
|
|
"Current question index in the Linux+ quiz buffer.")
|
|
|
|
(defvar-local linuxplus-quiz-lesson-name nil
|
|
"Lesson name associated with the current Linux+ quiz buffer.")
|
|
|
|
(defun linuxplus-quiz-answer-marker (answer)
|
|
"Return a display marker string for ANSWER."
|
|
(cond
|
|
((eq answer 'y) "[y]")
|
|
((eq answer 'n) "[n]")
|
|
(t "[ ]")))
|
|
|
|
(defun linuxplus-quiz-answer-string (answer)
|
|
"Return a readable string for ANSWER."
|
|
(cond
|
|
((eq answer 'y) "y")
|
|
((eq answer 'n) "n")
|
|
(t "unanswered")))
|
|
|
|
(defun linuxplus-quiz-result-string (user-answer correct-answer)
|
|
"Return a readable result string comparing USER-ANSWER to CORRECT-ANSWER."
|
|
(if (eq user-answer correct-answer)
|
|
"correct"
|
|
"incorrect"))
|
|
|
|
(defun linuxplus-quiz-render ()
|
|
"Render the current Linux+ quiz buffer."
|
|
(let ((inhibit-read-only t))
|
|
(erase-buffer)
|
|
(insert "Linux+ Quiz\n")
|
|
(insert "===========\n\n")
|
|
(insert "y = yes, n = no, b = back, f = forward, x = finish, q = quit\n\n")
|
|
(dotimes (i (length linuxplus-quiz-questions))
|
|
(let ((prefix (if (= i linuxplus-quiz-current-index) ">" " "))
|
|
(marker (linuxplus-quiz-answer-marker
|
|
(nth i linuxplus-quiz-user-answers)))
|
|
(question (nth i linuxplus-quiz-questions)))
|
|
(insert (format "%s %s %d. %s\n"
|
|
prefix marker (1+ i) question)))))
|
|
(goto-char (point-min)))
|
|
|
|
(defun linuxplus-quiz-finish ()
|
|
"Finish the current quiz, record the score, and show detailed results."
|
|
(interactive)
|
|
(let ((score 0)
|
|
(total (length linuxplus-quiz-questions)))
|
|
(dotimes (i total)
|
|
(when (eq (nth i linuxplus-quiz-user-answers)
|
|
(nth i linuxplus-quiz-answers))
|
|
(setq score (1+ score))))
|
|
(linuxplus-record-score linuxplus-quiz-lesson-name score)
|
|
(let ((inhibit-read-only t))
|
|
(erase-buffer)
|
|
(insert "Linux+ Quiz Results\n")
|
|
(insert "===================\n\n")
|
|
(insert (format "Lesson: %s\n" linuxplus-quiz-lesson-name))
|
|
(insert (format "Score: %d/%d\n\n" score total))
|
|
(insert "Detailed review:\n\n")
|
|
(dotimes (i total)
|
|
(let ((question (nth i linuxplus-quiz-questions))
|
|
(user-answer (nth i linuxplus-quiz-user-answers))
|
|
(correct-answer (nth i linuxplus-quiz-answers)))
|
|
(insert (format "%d. %s\n" (1+ i) question))
|
|
(insert (format " Your answer: %s\n"
|
|
(linuxplus-quiz-answer-string user-answer)))
|
|
(insert (format " Correct answer: %s\n"
|
|
(linuxplus-quiz-answer-string correct-answer)))
|
|
(insert (format " Result: %s\n\n"
|
|
(linuxplus-quiz-result-string
|
|
user-answer correct-answer))))))
|
|
(goto-char (point-min))
|
|
(view-mode 1)
|
|
(message "Quiz complete. Score: %d/%d" score total)))
|
|
|
|
(defun linuxplus-quiz-answer-y ()
|
|
"Answer yes to the current Linux+ quiz question."
|
|
(interactive)
|
|
(setf (nth linuxplus-quiz-current-index linuxplus-quiz-user-answers) 'y)
|
|
(if (< linuxplus-quiz-current-index
|
|
(1- (length linuxplus-quiz-questions)))
|
|
(setq linuxplus-quiz-current-index
|
|
(1+ linuxplus-quiz-current-index))
|
|
(linuxplus-quiz-render))
|
|
(when (derived-mode-p 'linuxplus-quiz-mode)
|
|
(linuxplus-quiz-render)))
|
|
|
|
(defun linuxplus-quiz-answer-n ()
|
|
"Answer no to the current Linux+ quiz question."
|
|
(interactive)
|
|
(setf (nth linuxplus-quiz-current-index linuxplus-quiz-user-answers) 'n)
|
|
(if (< linuxplus-quiz-current-index
|
|
(1- (length linuxplus-quiz-questions)))
|
|
(setq linuxplus-quiz-current-index
|
|
(1+ linuxplus-quiz-current-index))
|
|
(linuxplus-quiz-render))
|
|
(when (derived-mode-p 'linuxplus-quiz-mode)
|
|
(linuxplus-quiz-render)))
|
|
|
|
(defun linuxplus-quiz-next ()
|
|
"Move to next question without changing answer."
|
|
(interactive)
|
|
(when (< linuxplus-quiz-current-index
|
|
(1- (length linuxplus-quiz-questions)))
|
|
(setq linuxplus-quiz-current-index
|
|
(1+ linuxplus-quiz-current-index))
|
|
(linuxplus-quiz-render)))
|
|
|
|
(defun linuxplus-quiz-prev ()
|
|
"Move to previous question."
|
|
(interactive)
|
|
(when (> linuxplus-quiz-current-index 0)
|
|
(setq linuxplus-quiz-current-index
|
|
(1- linuxplus-quiz-current-index))
|
|
(linuxplus-quiz-render)))
|
|
|
|
(defvar linuxplus-quiz-mode-map
|
|
(let ((map (make-sparse-keymap)))
|
|
(define-key map (kbd "y") #'linuxplus-quiz-answer-y)
|
|
(define-key map (kbd "n") #'linuxplus-quiz-answer-n)
|
|
(define-key map (kbd "f") #'linuxplus-quiz-next)
|
|
(define-key map (kbd "b") #'linuxplus-quiz-prev)
|
|
(define-key map (kbd "x") #'linuxplus-quiz-finish)
|
|
(define-key map (kbd "q") #'quit-window)
|
|
map)
|
|
"Keymap for `linuxplus-quiz-mode`.")
|
|
|
|
(define-derived-mode linuxplus-quiz-mode special-mode "LinuxPlus-Quiz"
|
|
"Major mode for Linux+ quiz buffers."
|
|
(setq buffer-read-only t))
|
|
|
|
(defun linuxplus-start-quiz (lesson questions answers buffer)
|
|
"Start a Linux+ quiz for LESSON using QUESTIONS and ANSWERS in BUFFER."
|
|
(let ((buf (get-buffer-create buffer)))
|
|
(with-current-buffer buf
|
|
(linuxplus-quiz-mode)
|
|
(setq linuxplus-quiz-lesson-name lesson)
|
|
(setq linuxplus-quiz-questions questions)
|
|
(setq linuxplus-quiz-answers answers)
|
|
(setq linuxplus-quiz-user-answers (make-list (length questions) nil))
|
|
(setq linuxplus-quiz-current-index 0)
|
|
(linuxplus-quiz-render))
|
|
(pop-to-buffer buf)))
|
|
|
|
;;; 06-linuxplus-quiz-mode.el ends here
|