akinator
This commit is contained in:
parent
e1f2465204
commit
50af52f2e4
5 changed files with 320 additions and 7 deletions
13
pom.xml
13
pom.xml
|
@ -33,7 +33,7 @@
|
||||||
</filter>
|
</filter>
|
||||||
</filters>
|
</filters>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<minimizeJar>true</minimizeJar>
|
<minimizeJar>false</minimizeJar>
|
||||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
@ -80,12 +80,12 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>2.0.1</version>
|
<version>2.0.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-simple</artifactId>
|
<artifactId>slf4j-simple</artifactId>
|
||||||
<version>2.0.1</version>
|
<version>2.0.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sedmelluq</groupId>
|
<groupId>com.sedmelluq</groupId>
|
||||||
|
@ -110,7 +110,12 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>org.json</groupId>
|
||||||
<artifactId>json</artifactId>
|
<artifactId>json</artifactId>
|
||||||
<version>20220320</version>
|
<version>20220924</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.markozajc</groupId>
|
||||||
|
<artifactId>akiwrapper</artifactId>
|
||||||
|
<version>1.5.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mariadb.jdbc</groupId>
|
<groupId>org.mariadb.jdbc</groupId>
|
||||||
|
|
|
@ -95,7 +95,8 @@ public class Responder extends ListenerAdapter {
|
||||||
new UnMute(),
|
new UnMute(),
|
||||||
new SetJoining(),
|
new SetJoining(),
|
||||||
new History(),
|
new History(),
|
||||||
new Sticker()
|
new Sticker(),
|
||||||
|
new Akinator()
|
||||||
};
|
};
|
||||||
Arrays.stream(objects).forEach(register::register);
|
Arrays.stream(objects).forEach(register::register);
|
||||||
}
|
}
|
||||||
|
@ -194,13 +195,14 @@ public class Responder extends ListenerAdapter {
|
||||||
try {
|
try {
|
||||||
event.deferEdit().queue();
|
event.deferEdit().queue();
|
||||||
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
|
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
|
||||||
|
if(temp == null) return;
|
||||||
Response response = (Response) temp;
|
Response response = (Response) temp;
|
||||||
edit(response, event.getHook());
|
edit(response, event.getHook());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
|
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
|
||||||
.setColor(Color.RED)
|
.setColor(Color.RED)
|
||||||
.setTitle(":x: **Error**")
|
.setTitle(":x: **Error**")
|
||||||
.setDescription(e.getCause().getMessage());
|
.setDescription(e.getCause() != null ? e.getCause().getMessage() : "An unknown error has occurred");
|
||||||
event.getHook().editOriginalEmbeds(builder.build()).queue();
|
event.getHook().editOriginalEmbeds(builder.build()).queue();
|
||||||
event.getHook().editOriginalComponents(new ArrayList<>()).queue();
|
event.getHook().editOriginalComponents(new ArrayList<>()).queue();
|
||||||
}
|
}
|
||||||
|
@ -242,6 +244,10 @@ public class Responder extends ListenerAdapter {
|
||||||
// Invoke Method and Respond to User
|
// Invoke Method and Respond to User
|
||||||
try {
|
try {
|
||||||
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
|
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
|
||||||
|
if(temp == null) {
|
||||||
|
event.reply("You dont have permission to use this!").setEphemeral(true).queue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
Response response = (Response) temp;
|
Response response = (Response) temp;
|
||||||
event.deferReply(response.isError()).queue();
|
event.deferReply(response.isError()).queue();
|
||||||
reply(response, event.getHook());
|
reply(response, event.getHook());
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class Response {
|
||||||
private String fileName;
|
private String fileName;
|
||||||
|
|
||||||
private boolean hidden = false;
|
private boolean hidden = false;
|
||||||
|
private boolean removeComponents = false;
|
||||||
|
|
||||||
public static Response error(String message){
|
public static Response error(String message){
|
||||||
Response response = new Response();
|
Response response = new Response();
|
||||||
|
@ -94,6 +95,11 @@ public class Response {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Response setRemoveComponents(boolean removeComponents) {
|
||||||
|
this.removeComponents = removeComponents;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isError(){
|
public boolean isError(){
|
||||||
return type.equals("error");
|
return type.equals("error");
|
||||||
}
|
}
|
||||||
|
@ -110,6 +116,8 @@ public class Response {
|
||||||
|
|
||||||
public boolean hasSelectMenu() { return menu != null; }
|
public boolean hasSelectMenu() { return menu != null; }
|
||||||
|
|
||||||
|
public boolean hasNoComponents() { return removeComponents; }
|
||||||
|
|
||||||
public Button[] getButtons() {
|
public Button[] getButtons() {
|
||||||
Button[] arr = new Button[buttons.size()];
|
Button[] arr = new Button[buttons.size()];
|
||||||
arr = buttons.toArray(arr);
|
arr = buttons.toArray(arr);
|
||||||
|
|
293
src/main/java/net/tylermurphy/ken/command/game/Akinator.java
Normal file
293
src/main/java/net/tylermurphy/ken/command/game/Akinator.java
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
package net.tylermurphy.ken.command.game;
|
||||||
|
|
||||||
|
import com.github.markozajc.akiwrapper.Akiwrapper;
|
||||||
|
import com.github.markozajc.akiwrapper.AkiwrapperBuilder;
|
||||||
|
import com.github.markozajc.akiwrapper.core.entities.Guess;
|
||||||
|
import com.github.markozajc.akiwrapper.core.entities.Identifiable;
|
||||||
|
import com.github.markozajc.akiwrapper.core.entities.Question;
|
||||||
|
import com.github.markozajc.akiwrapper.core.exceptions.ServerNotFoundException;
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||||
|
import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
|
||||||
|
import net.tylermurphy.ken.Ken;
|
||||||
|
import net.tylermurphy.ken.command.Response;
|
||||||
|
import net.tylermurphy.ken.command.annotation.ButtonCallback;
|
||||||
|
import net.tylermurphy.ken.command.annotation.Command;
|
||||||
|
import net.tylermurphy.ken.util.Checks;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Akinator {
|
||||||
|
|
||||||
|
protected Map<Long, Integer> gameMappings = new HashMap<>();
|
||||||
|
protected Map<Integer, AkinatorGame> games = new HashMap<>();
|
||||||
|
|
||||||
|
@Command(name="akinator", description="Plays akinator")
|
||||||
|
public Response execute(Member sender, GuildMessageChannel channel) {
|
||||||
|
if(gameMappings.containsKey(sender.getIdLong())) {
|
||||||
|
games.remove(gameMappings.get(sender.getIdLong()));
|
||||||
|
gameMappings.remove(sender.getIdLong());
|
||||||
|
}
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
AkinatorGame game = new AkinatorGame(sender, this);
|
||||||
|
gameMappings.put(sender.getIdLong(), game.getGameId());
|
||||||
|
games.put(game.getGameId(), game);
|
||||||
|
Response response = game.respond(null);
|
||||||
|
channel.sendMessageEmbeds(response.getEmbeds()).setActionRow(response.getButtons()).queue();
|
||||||
|
} catch (ServerNotFoundException e) {
|
||||||
|
channel.sendMessage(":x: Failed to connect to Akinator").queue();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
return Response.success(":arrows_clockwise: Connecting to Akinator");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ButtonCallback(name="akinator")
|
||||||
|
public Response onButton(String id, Message message, Member sender) {
|
||||||
|
|
||||||
|
try { Checks.hasPagedEmbed(message); }
|
||||||
|
catch (RuntimeException e) { return Response.error(e.getMessage()); }
|
||||||
|
|
||||||
|
int gameId = Integer.parseInt(message.getEmbeds().get(0).getFooter().getText().substring(9));
|
||||||
|
|
||||||
|
AkinatorGame game = games.get(gameId);
|
||||||
|
if(game == null) {
|
||||||
|
return Response.error("Game has ended");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(game.getUserId() != sender.getIdLong()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return game.respond(id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AkiStatus {
|
||||||
|
QUESTION,
|
||||||
|
GUESS,
|
||||||
|
CONTINUE
|
||||||
|
}
|
||||||
|
|
||||||
|
class AkinatorGame {
|
||||||
|
|
||||||
|
private static int lastGameId = 0;
|
||||||
|
|
||||||
|
private final Akinator container;
|
||||||
|
private final Akiwrapper wrapper;
|
||||||
|
private final List<Identifiable> sequence;
|
||||||
|
private final List<String> guesses;
|
||||||
|
|
||||||
|
private final String displayName;
|
||||||
|
private final long userId;
|
||||||
|
|
||||||
|
private final int gameId;
|
||||||
|
|
||||||
|
private AkiStatus status;
|
||||||
|
private int questionNumber;
|
||||||
|
private int sequenceIndex;
|
||||||
|
private int attemptedGuesses;
|
||||||
|
|
||||||
|
|
||||||
|
public AkinatorGame(Member member, Akinator container) throws ServerNotFoundException {
|
||||||
|
this.container = container;
|
||||||
|
this.wrapper = new AkiwrapperBuilder().build();
|
||||||
|
this.sequence = new LinkedList<>();
|
||||||
|
this.guesses = new LinkedList<>();
|
||||||
|
|
||||||
|
this.displayName = member.getEffectiveName();
|
||||||
|
this.userId = member.getUser().getIdLong();
|
||||||
|
|
||||||
|
this.gameId = lastGameId++;
|
||||||
|
|
||||||
|
this.status = AkiStatus.QUESTION;
|
||||||
|
this.questionNumber = 0;
|
||||||
|
this.sequenceIndex = -1;
|
||||||
|
this.attemptedGuesses = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGameId() {
|
||||||
|
return gameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response respond(String label) {
|
||||||
|
if(label == null) return next();
|
||||||
|
if(status == AkiStatus.GUESS) {
|
||||||
|
return respondGuess(label);
|
||||||
|
} else if (status == AkiStatus.QUESTION) {
|
||||||
|
return respondQuestion(label);
|
||||||
|
} else if (status == AkiStatus.CONTINUE) {
|
||||||
|
return respondContinue(label);
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Failed to respond to user input");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response respondGuess(String label) {
|
||||||
|
switch (label) {
|
||||||
|
case "yes":
|
||||||
|
container.games.remove(gameId);
|
||||||
|
container.gameMappings.remove(userId);
|
||||||
|
return sendLoose();
|
||||||
|
case "no":
|
||||||
|
status = AkiStatus.CONTINUE;
|
||||||
|
return sendContinue();
|
||||||
|
case "back":
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Failed to respond to user input");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response respondContinue(String label) {
|
||||||
|
switch (label) {
|
||||||
|
case "yes":
|
||||||
|
return next();
|
||||||
|
case "no":
|
||||||
|
container.games.remove(gameId);
|
||||||
|
container.gameMappings.remove(userId);
|
||||||
|
return sendWin();
|
||||||
|
case "back":
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Failed to respond to user input");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response respondQuestion(String label) {
|
||||||
|
switch (label) {
|
||||||
|
case "yes":
|
||||||
|
wrapper.answer(Akiwrapper.Answer.YES);
|
||||||
|
break;
|
||||||
|
case "no":
|
||||||
|
wrapper.answer(Akiwrapper.Answer.NO);
|
||||||
|
break;
|
||||||
|
case "idk":
|
||||||
|
wrapper.answer(Akiwrapper.Answer.DONT_KNOW);
|
||||||
|
break;
|
||||||
|
case "back":
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response next() {
|
||||||
|
sequenceIndex++;
|
||||||
|
Optional<Guess> guess = wrapper.getGuesses().stream().filter(g -> g.getProbability() > .85 && !guesses.contains(g.getId())).reduce((first, second) -> second);
|
||||||
|
if(guess.isPresent()) {
|
||||||
|
status = AkiStatus.GUESS;
|
||||||
|
sequence.add(guess.get());
|
||||||
|
attemptedGuesses++;
|
||||||
|
return sendGuess(guess.get());
|
||||||
|
} else {
|
||||||
|
status = AkiStatus.QUESTION;
|
||||||
|
Question question = wrapper.getQuestion();
|
||||||
|
sequence.add(question);
|
||||||
|
questionNumber++;
|
||||||
|
if(question == null) {
|
||||||
|
// remove game
|
||||||
|
return sendWin();
|
||||||
|
}
|
||||||
|
return sendQuestion(question);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response back() {
|
||||||
|
sequenceIndex--;
|
||||||
|
Identifiable current = sequence.get(sequenceIndex+1);
|
||||||
|
if(current instanceof Guess) {
|
||||||
|
attemptedGuesses--;
|
||||||
|
guesses.remove(guesses.size() - 1);
|
||||||
|
sequence.remove(current);
|
||||||
|
} else if(current instanceof Question) {
|
||||||
|
questionNumber--;
|
||||||
|
sequence.remove(current);
|
||||||
|
}
|
||||||
|
Identifiable previous = sequence.get(sequenceIndex);
|
||||||
|
if(previous instanceof Guess guess) {
|
||||||
|
status = AkiStatus.GUESS;
|
||||||
|
return sendGuess(guess);
|
||||||
|
} else if(previous instanceof Question question){
|
||||||
|
status = AkiStatus.QUESTION;
|
||||||
|
return sendQuestion(question);
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Failed to go back in sequence");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response sendGuess(Guess guess) {
|
||||||
|
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
|
||||||
|
builder.setAuthor("Akinator: " + displayName);
|
||||||
|
builder.setTitle("Is this your character?");
|
||||||
|
builder.appendDescription("**" + guess.getName() + "**\n" + guess.getDescription());
|
||||||
|
builder.setImage(guess.getImage().toExternalForm());
|
||||||
|
builder.setFooter("Game id: " + gameId);
|
||||||
|
Response response = Response.success(builder.build())
|
||||||
|
.addPrimaryButton("akinator", "yes", "Yes")
|
||||||
|
.addPrimaryButton("akinator", "no", "No");
|
||||||
|
if(sequenceIndex > 0)
|
||||||
|
response.addSecondaryButton("akinator", "back", "Back");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response sendQuestion(Question question) {
|
||||||
|
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
|
||||||
|
builder.setAuthor("Akinator: " + displayName);
|
||||||
|
builder.setTitle("Question " + questionNumber);
|
||||||
|
builder.appendDescription(question.getQuestion());
|
||||||
|
builder.setFooter("Game id: " + gameId);
|
||||||
|
Response response = Response.success(builder.build())
|
||||||
|
.addPrimaryButton("akinator", "yes", "Yes")
|
||||||
|
.addPrimaryButton("akinator", "no", "No")
|
||||||
|
.addPrimaryButton("akinator", "idk", "IDK");
|
||||||
|
if(sequenceIndex > 0)
|
||||||
|
response.addSecondaryButton("akinator", "back", "Back");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response sendContinue() {
|
||||||
|
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
|
||||||
|
builder.setAuthor("Akinator: " + displayName);
|
||||||
|
builder.setTitle("Continue?");
|
||||||
|
builder.appendDescription("Akinator guessed incorrectly, would you like to continue?");
|
||||||
|
builder.setFooter("Game id: " + gameId);
|
||||||
|
Response response = Response.success(builder.build())
|
||||||
|
.addPrimaryButton("akinator", "yes", "Yes")
|
||||||
|
.addPrimaryButton("akinator", "no", "No");
|
||||||
|
if(sequenceIndex > 0)
|
||||||
|
response.addSecondaryButton("akinator", "back", "Back");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response sendWin() {
|
||||||
|
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
|
||||||
|
builder.setAuthor("Akinator: " + displayName);
|
||||||
|
builder.setTitle("You win!");
|
||||||
|
builder.appendDescription("Total guesses: " + attemptedGuesses + "\n");
|
||||||
|
builder.appendDescription("Total questions: " + questionNumber);
|
||||||
|
builder.setFooter("Game id: " + gameId);
|
||||||
|
builder.setColor(new Color(130,255,130));
|
||||||
|
return Response.success(builder.build()).setRemoveComponents(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response sendLoose() {
|
||||||
|
Guess guess = (Guess) sequence.get(sequenceIndex);
|
||||||
|
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
|
||||||
|
builder.setAuthor("Akinator: " + displayName);
|
||||||
|
builder.setTitle("You loose :(");
|
||||||
|
builder.appendDescription("Total guesses: " + attemptedGuesses + "\n");
|
||||||
|
builder.appendDescription("Total questions: " + questionNumber + "\n");
|
||||||
|
builder.appendDescription("Character Guessed: " + guess.getName());
|
||||||
|
builder.setImage(guess.getImage().toExternalForm());
|
||||||
|
builder.setFooter("Game id: " + gameId);
|
||||||
|
builder.setColor(new Color(255,130,130));
|
||||||
|
return Response.success(builder.build()).setRemoveComponents(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -88,7 +88,8 @@ public class Help {
|
||||||
.appendDescription("**/claim** Claim moneys every 24h\n")
|
.appendDescription("**/claim** Claim moneys every 24h\n")
|
||||||
.appendDescription("**/money** Check how much moneys you have\n")
|
.appendDescription("**/money** Check how much moneys you have\n")
|
||||||
.appendDescription("**/roulette <bet>** Gamble on roulette\n")
|
.appendDescription("**/roulette <bet>** Gamble on roulette\n")
|
||||||
.appendDescription("**/slots <bet>** Gamble on slots\n"),
|
.appendDescription("**/slots <bet>** Gamble on slots\n")
|
||||||
|
.appendDescription("**/akinator** Play akinator\n"),
|
||||||
Ken.getInstance().getDefaultEmbed()
|
Ken.getInstance().getDefaultEmbed()
|
||||||
.setAuthor("Command List")
|
.setAuthor("Command List")
|
||||||
.setTitle(":desktop: **Social Commands**")
|
.setTitle(":desktop: **Social Commands**")
|
||||||
|
|
Loading…
Reference in a new issue