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>
|
||||
</filters>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
|
@ -80,12 +80,12 @@
|
|||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sedmelluq</groupId>
|
||||
|
@ -110,7 +110,12 @@
|
|||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<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>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
|
|
|
@ -95,7 +95,8 @@ public class Responder extends ListenerAdapter {
|
|||
new UnMute(),
|
||||
new SetJoining(),
|
||||
new History(),
|
||||
new Sticker()
|
||||
new Sticker(),
|
||||
new Akinator()
|
||||
};
|
||||
Arrays.stream(objects).forEach(register::register);
|
||||
}
|
||||
|
@ -194,13 +195,14 @@ public class Responder extends ListenerAdapter {
|
|||
try {
|
||||
event.deferEdit().queue();
|
||||
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
|
||||
if(temp == null) return;
|
||||
Response response = (Response) temp;
|
||||
edit(response, event.getHook());
|
||||
} catch (Exception e) {
|
||||
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
|
||||
.setColor(Color.RED)
|
||||
.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().editOriginalComponents(new ArrayList<>()).queue();
|
||||
}
|
||||
|
@ -242,6 +244,10 @@ public class Responder extends ListenerAdapter {
|
|||
// Invoke Method and Respond to User
|
||||
try {
|
||||
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;
|
||||
event.deferReply(response.isError()).queue();
|
||||
reply(response, event.getHook());
|
||||
|
|
|
@ -22,6 +22,7 @@ public class Response {
|
|||
private String fileName;
|
||||
|
||||
private boolean hidden = false;
|
||||
private boolean removeComponents = false;
|
||||
|
||||
public static Response error(String message){
|
||||
Response response = new Response();
|
||||
|
@ -94,6 +95,11 @@ public class Response {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Response setRemoveComponents(boolean removeComponents) {
|
||||
this.removeComponents = removeComponents;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isError(){
|
||||
return type.equals("error");
|
||||
}
|
||||
|
@ -110,6 +116,8 @@ public class Response {
|
|||
|
||||
public boolean hasSelectMenu() { return menu != null; }
|
||||
|
||||
public boolean hasNoComponents() { return removeComponents; }
|
||||
|
||||
public Button[] getButtons() {
|
||||
Button[] arr = new Button[buttons.size()];
|
||||
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("**/money** Check how much moneys you have\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()
|
||||
.setAuthor("Command List")
|
||||
.setTitle(":desktop: **Social Commands**")
|
||||
|
|
Loading…
Reference in a new issue