package uk.co.bytemark.vm.enigma.inquisition.quiz; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import uk.co.bytemark.vm.enigma.inquisition.gui.misc.QuizConfig; import uk.co.bytemark.vm.enigma.inquisition.misc.Constants; import uk.co.bytemark.vm.enigma.inquisition.misc.Utils; import uk.co.bytemark.vm.enigma.inquisition.questions.DragAndDropQuestion; import uk.co.bytemark.vm.enigma.inquisition.questions.DragAndDropRenderingHelper; import uk.co.bytemark.vm.enigma.inquisition.questions.MultipleChoiceQuestion; import uk.co.bytemark.vm.enigma.inquisition.questions.MultipleChoiceQuestionInstance; import uk.co.bytemark.vm.enigma.inquisition.questions.MultipleChoiceRenderingHelper; import uk.co.bytemark.vm.enigma.inquisition.questions.Option; import uk.co.bytemark.vm.enigma.inquisition.questions.Question; import uk.co.bytemark.vm.enigma.inquisition.questions.QuestionRenderingHelper; import uk.co.bytemark.vm.enigma.inquisition.questions.QuestionSet; import uk.co.bytemark.vm.enigma.inquisition.questions.QuestionSetManager; public class HTMLQuizRenderer { private final QuizConfig quizConfig; private final boolean showAnswers; private final boolean repeatMultipleChoiceQuestionInAnswer; private final boolean addLinksBetweenQuestionsAndAnswers; public HTMLQuizRenderer(QuizConfig quizConfig, boolean showAnswers, boolean repeatMultipleChoiceQuestionInAnswer, boolean addLinksBetweenQuestionsAndAnswers) { if (!showAnswers && (repeatMultipleChoiceQuestionInAnswer || addLinksBetweenQuestionsAndAnswers)) throw new IllegalArgumentException("Invalid combination of rendering options"); this.quizConfig = quizConfig; this.showAnswers = showAnswers; this.repeatMultipleChoiceQuestionInAnswer = repeatMultipleChoiceQuestionInAnswer; this.addLinksBetweenQuestionsAndAnswers = addLinksBetweenQuestionsAndAnswers; } public String asHtml(QuestionSet questionSet) { StringBuilder builder = new StringBuilder(); String questionSetName = questionSet.getName(); builder.append("<html><head><title>").append(questionSetName).append("</title></head>"); builder.append("<body>"); builder.append("<h1>").append(questionSetName).append("</h1>"); builder.append("<h1>").append("Description").append("</h1>"); builder.append(questionSet.getDescription()); List<Question> questions = new ArrayList<Question>(questionSet.getQuestions()); if (quizConfig.shouldShuffleQuestionOrder()) Collections.shuffle(questions); builder.append("<h1>").append("Questions").append("</h1>"); int questionCounter = 1; Map<MultipleChoiceQuestion, MultipleChoiceQuestionInstance> optionsMap = Utils.newHashMap(); for (Question genericQuestion : questions) { builder.append("<h2>").append("<a name='question").append(questionCounter).append("'>"); builder.append("Question ").append(questionCounter); builder.append("</a>").append("</h2>"); if (genericQuestion instanceof MultipleChoiceQuestion) { MultipleChoiceQuestion question = (MultipleChoiceQuestion) genericQuestion; MultipleChoiceQuestionInstance questionInstance = new MultipleChoiceQuestionInstance(question); optionsMap.put(question, questionInstance); builder.append(renderMultipleChoiceQuestion(question, questionInstance, false)); } else if (genericQuestion instanceof DragAndDropQuestion) { DragAndDropQuestion question = (DragAndDropQuestion) genericQuestion; builder.append(renderDragAndDropQuestion(question, false)); } if (showAnswers && addLinksBetweenQuestionsAndAnswers) builder.append("<p><a href='#answer").append(questionCounter).append("'>").append("Go to answer") .append("</a>"); questionCounter++; } if (showAnswers) { builder.append("<h1>").append("Answers").append("</h1>"); questionCounter = 1; for (Question genericQuestion : questions) { builder.append("<h2>").append("<a name='answer").append(questionCounter).append("'>"); builder.append("Answer To Question ").append(questionCounter); builder.append("</a>").append("</h2>"); if (genericQuestion instanceof MultipleChoiceQuestion) { MultipleChoiceQuestion question = (MultipleChoiceQuestion) genericQuestion; MultipleChoiceQuestionInstance questionInstance = optionsMap.get(question); builder.append(renderMultipleChoiceQuestion(question, questionInstance, true)); } else if (genericQuestion instanceof DragAndDropQuestion) { DragAndDropQuestion question = (DragAndDropQuestion) genericQuestion; builder.append(renderDragAndDropQuestion(question, true)); } if (addLinksBetweenQuestionsAndAnswers) builder.append("<p><a href='#question").append(questionCounter).append("'>").append( "Go to question").append("</a>"); questionCounter++; } } builder .append("<hr><center><font size='-1'>Generated by <a href='http://enigma.vm.bytemark.co.uk/inquisition'>Inquisition v" + Constants.VERSION + "</a></font></center>"); builder.append("</body></html>"); return builder.toString(); } private String renderDragAndDropQuestion(DragAndDropQuestion question, boolean explanation) { StringBuilder builder = new StringBuilder(); String questionText = DragAndDropRenderingHelper.getQuestionText(question, false); if (explanation) questionText = DragAndDropRenderingHelper.getExplanationText(question); builder.append(questionText); if (!explanation) { String optionsTitle = DragAndDropRenderingHelper.optionsTitle(question); builder.append("<br>" + optionsTitle + "<br>"); List<String> fragments = question.getFragments(); for (String fragment : fragments) { builder.append("<table border='1' bgcolor='#f4f4ff' cellspacing='0'><tr><td>" + fragment + "</td></tr></table>"); } builder.append("<p>"); } return builder.toString(); } private String renderMultipleChoiceQuestion(MultipleChoiceQuestion question, MultipleChoiceQuestionInstance questionInstance, boolean explanation) { StringBuilder builder = new StringBuilder(); if (!explanation || repeatMultipleChoiceQuestionInAnswer) { String questionText = QuestionRenderingHelper.syntaxHighlightForJava(question.getSubstitutedQuestionText()); builder.append(questionText); builder.append("<p>"); String optionsTitle = MultipleChoiceRenderingHelper.optionsTitle(question, quizConfig .shouldStateNumberOfOptionsNeededForMultipleChoice()); builder.append(optionsTitle).append(":"); } builder.append("<ol type='A'>"); int optionsCounter = 0; for (Option option : questionInstance.getOrderedOptions()) { String optionText = option.getOptionText(); boolean check = explanation ? option.isCorrect() : false; String checked = check ? "checked='true'" : ""; builder.append("<li>").append("<input type='checkbox' ").append(checked).append("'> ").append(optionText) .append("</li>"); optionsCounter++; } builder.append("</ol>"); if (explanation) { builder.append("<p>"); builder.append(MultipleChoiceRenderingHelper.getExplanationText(questionInstance)); } return builder.toString(); } // private static class HtmlViewerFrame extends JFrame { // public HtmlViewerFrame(String html) { // JTextPane textPane = new JTextPane(); // textPane.setContentType("text/html"); // textPane.setText(html); // add(new JScrollPane(textPane), BorderLayout.CENTER); // setDefaultCloseOperation(EXIT_ON_CLOSE); // pack(); // } // } public static void main(String[] args) { File rootDir = new File(System.getProperty("java.io.tmpdir"), "inquisition-quizzes"); if (!rootDir.exists()) { boolean succeeded = rootDir.mkdir(); if (!succeeded) { System.err.println("Could not create directory " + rootDir.getAbsolutePath()); return; } } Logger logger = Logger.getLogger(""); logger.setLevel(Level.WARNING); StringBuilder builder = new StringBuilder( "<html><body><h1>Inquisition Quizzes</h1>" + "The following have been generated by <a href='http://enigma.vm.bytemark.co.uk/inquisition'>Inquisition</a>, an open-source " + "mock exam engine.<ul>"); HTMLQuizRenderer quizRenderer = makeHtmlRenderer(); int count = 0; for (QuestionSet questionSet : QuestionSetManager.loadBundledQuestionSets()) { System.out.println("Processing " + questionSet.getName()); String fileName = "quiz" + count + ".html"; builder.append("<li><a href='").append(fileName).append("'>").append(questionSet.getCategorySequence()) .append(" -- ").append(questionSet.getName()).append("</a></li>"); final String html = quizRenderer.asHtml(questionSet); try { File location = new File(rootDir, fileName); PrintWriter printWriter = new PrintWriter(location); printWriter.write(html); printWriter.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } count++; } builder.append("</ul></body></html>"); File location = new File(rootDir, "index.html"); PrintWriter printWriter; try { printWriter = new PrintWriter(location); printWriter.write(builder.toString()); printWriter.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("Output index:"); System.out.println("file://" + location.getAbsolutePath()); // SwingUtilities.invokeLater(new Runnable() { // public void run() { // HtmlViewerFrame htmlViewer = new HtmlViewerFrame(html); // htmlViewer.setVisible(true); // } // }); } private static HTMLQuizRenderer makeHtmlRenderer() { QuizConfig quizConfig = QuizConfig.createWithTimer(false, true, 30); boolean showAnswers = true; boolean repeatMultipleChoiceQuestionInAnswer = false; boolean addLinksBetweenQuestionsAndAnswers = true; HTMLQuizRenderer printableQuizCreator = new HTMLQuizRenderer(quizConfig, showAnswers, repeatMultipleChoiceQuestionInAnswer, addLinksBetweenQuestionsAndAnswers); return printableQuizCreator; } }