-
Notifications
You must be signed in to change notification settings - Fork 5
feat: add QuizQuestion and TriviaManager classes for Java trivia game #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 4 commits
492d648
06d3d1c
7d966cc
73890ed
6e09485
ab3d603
607ec27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.togetherjava.tjplays.games.game2048; | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonCreator; | ||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record QuizQuestion( | ||
| @JsonProperty("question") String question, | ||
| @JsonProperty("choices") List<String> choices, | ||
| @JsonProperty("correct") int correctIndex | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: It took me a little bit to understand what |
||
| ) { | ||
| @JsonCreator | ||
| public QuizQuestion {} | ||
|
|
||
| public String getQuestion() { | ||
| return question; | ||
| } | ||
|
|
||
| public List<String> getChoices() { | ||
| return choices; | ||
| } | ||
|
|
||
| public int getCorrectIndex() { | ||
| return correctIndex; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.togetherjava.tjplays.games.game2048; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this class part of the |
||
|
|
||
| import com.togetherjava.tjplays.services.chatgpt.ChatGptService; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| public class TriviaManager { | ||
| private final ChatGptService gpt; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please properly name this variable to |
||
| private final ObjectMapper mapper = new ObjectMapper(); | ||
|
|
||
| public TriviaManager(String openAiKey) { | ||
| this.gpt = new ChatGptService(openAiKey); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should give people the opportunity to pass |
||
| } | ||
|
|
||
| public Optional<QuizQuestion> fetchRandomQuestion() { | ||
| String prompt = "Provide one Java trivia question as a JSON object like" | ||
| + " {\"question\":\"...\",\"choices\":[\"A\",\"B\",\"C\",\"D\"],\"correct\":<index>}"; | ||
| Optional<String> raw = gpt.ask(prompt, "java quiz"); | ||
| if (raw.isEmpty()) { | ||
| return Optional.empty(); | ||
| } | ||
| try { | ||
| QuizQuestion question = mapper.readValue(raw.get(), QuizQuestion.class); | ||
| return Optional.of(question); | ||
| } catch (Exception e) { | ||
| return Optional.empty(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| package com.togetherjava.tjplays.listeners.commands; | ||
|
|
||
| import com.togetherjava.tjplays.games.game2048.QuizQuestion; | ||
| import com.togetherjava.tjplays.games.game2048.TriviaManager; | ||
|
|
||
| import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; | ||
| import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; | ||
| import net.dv8tion.jda.api.interactions.commands.build.Commands; | ||
| import net.dv8tion.jda.api.interactions.components.buttons.Button; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Optional; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
|
|
||
| public final class JavaQuizCommand extends SlashCommand { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once again, a JavaDoc would be useful here for future contributors as this is
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to extend |
||
| private static final String COMMAND_NAME = "javaquiz"; | ||
|
|
||
| private final TriviaManager triviaManager; | ||
| private final ConcurrentHashMap<String, QuizQuestion> activeQuestions = new ConcurrentHashMap<>(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why |
||
|
|
||
| public JavaQuizCommand(String openAiKey) { | ||
| super(Commands.slash(COMMAND_NAME, "Get a random Java trivia question")); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Once changing the extend, this will need to become:
|
||
| this.triviaManager = new TriviaManager(openAiKey); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just like in this code review comment, I believe that we should let callers pass down an instance of |
||
| } | ||
|
|
||
| @Override | ||
| public void onSlashCommand(SlashCommandInteractionEvent event) { | ||
| event.deferReply().queue(); | ||
|
|
||
| Optional<QuizQuestion> question = triviaManager.fetchRandomQuestion(); | ||
| if (question.isEmpty()) { | ||
| event.getHook().editOriginal("Could not fetch a quiz question. Try again later.").queue(); | ||
| return; | ||
| } | ||
|
|
||
| QuizQuestion q = question.get(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use proper variable names instead of a single letter for readability. |
||
| List<String> choices = q.getChoices(); | ||
|
|
||
| StringBuilder sb = new StringBuilder(); | ||
| sb.append("**Java Quiz**\n\n"); | ||
| sb.append(q.getQuestion()).append("\n\n"); | ||
| for (int i = 0; i < choices.size(); i++) { | ||
| sb.append("`").append(i + 1).append(")` ").append(choices.get(i)).append("\n"); | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not use A lot of things could be changed here, and the removal of Firstly, we should use Secondly, sending a |
||
|
|
||
| String messageId = event.getHook().editOriginal(sb.toString()) | ||
| .setActionRow( | ||
| Button.primary(COMMAND_NAME + "-1-" + event.getUser().getId(), "1"), | ||
| Button.primary(COMMAND_NAME + "-2-" + event.getUser().getId(), "2"), | ||
| Button.primary(COMMAND_NAME + "-3-" + event.getUser().getId(), "3"), | ||
| Button.primary(COMMAND_NAME + "-4-" + event.getUser().getId(), "4") | ||
| ) | ||
| .complete() | ||
| .getId(); | ||
|
|
||
| activeQuestions.put(messageId, q); | ||
| } | ||
|
|
||
| @Override | ||
| public void onButtonInteraction(ButtonInteractionEvent event) { | ||
| String buttonId = event.getButton().getId(); | ||
| if (buttonId == null || !buttonId.startsWith(COMMAND_NAME)) { | ||
| return; | ||
| } | ||
|
|
||
| if (!buttonId.contains(event.getUser().getId())) { | ||
| event.reply("This isn't your quiz!").setEphemeral(true).queue(); | ||
| return; | ||
| } | ||
|
|
||
| QuizQuestion q = activeQuestions.remove(event.getMessageId()); | ||
|
christolis marked this conversation as resolved.
Outdated
|
||
| if (q == null) { | ||
| event.reply("This quiz has already been answered.").setEphemeral(true).queue(); | ||
| return; | ||
| } | ||
|
|
||
| int chosen = Character.getNumericValue(buttonId.charAt(COMMAND_NAME.length() + 1)) - 1; | ||
| boolean correct = chosen == q.getCorrectIndex(); | ||
|
|
||
| String result = correct | ||
| ? "Correct! The answer is: **" + q.getChoices().get(q.getCorrectIndex()) + "**" | ||
| : "Wrong! The correct answer was: **" + q.getChoices().get(q.getCorrectIndex()) + "**"; | ||
|
christolis marked this conversation as resolved.
Outdated
|
||
|
|
||
| String userId = event.getUser().getId(); | ||
|
|
||
| event.editMessage(event.getMessage().getContentRaw() + "\n\n" + result) | ||
| .setActionRow( | ||
| Button.primary(COMMAND_NAME + "-1-" + userId, "1").asDisabled(), | ||
| Button.primary(COMMAND_NAME + "-2-" + userId, "2").asDisabled(), | ||
| Button.primary(COMMAND_NAME + "-3-" + userId, "3").asDisabled(), | ||
| Button.primary(COMMAND_NAME + "-4-" + userId, "4").asDisabled() | ||
| ) | ||
| .queue(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,7 +11,6 @@ | |
|
|
||
| import java.time.Duration; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps you need to rebase since this import does not exist on the main branch? |
||
| import java.util.Optional; | ||
|
|
||
| /** | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revert this file please - it's not needed to be changed. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| org.gradle.java.home=C:/Users/dudem/.gradle/jdks/eclipse_adoptium-21-amd64-windows/jdk-21.0.9+10 | ||
|
EJ-Edwards marked this conversation as resolved.
Outdated
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this class part of the
games.game2048package?