roll Implemntation

This commit is contained in:
Ocame
2025-07-17 23:02:05 +02:00
parent e2b9694e09
commit cb221e6bb2
4 changed files with 226 additions and 0 deletions

View File

@ -0,0 +1,101 @@
package de.ocame.wuerfelbot.Simpleroll;
import de.ocame.wuerfelbot.commands.ICommand;
import de.ocame.wuerfelbot.output.DiceOutputFormatter;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import java.util.Arrays;
import java.util.List;
public class SimplerollCommand implements ICommand {
private final SimplerollLogic rollLogic;
private final DiceOutputFormatter outputFormatter;
public SimplerollCommand() {
this.rollLogic = new SimplerollLogic();
this.outputFormatter = new DiceOutputFormatter();
}
@Override
public String getName() {
// Der primäre Name für den Text-Befehl
return "roll";
}
@Override
public String getDescription() {
return "Würfelt Würfel nach verschiedenen Notationen (z.B. 9, 9d4, 3w8, 9 +4).";
}
// --- Slash Command Handling (Wird leer gelassen oder eine Fehlermeldung gesendet) ---
@Override
public void executeSlash(SlashCommandInteractionEvent event) {
// Dieser Befehl ist nicht für Slash-Commands vorgesehen.
event.reply(outputFormatter.formatError("Dieser Befehl ist nur als Text-Befehl (!roll oder !r) verfügbar.")).setEphemeral(true).queue();
}
// --- Text Command Handling (Bestehend, mit Erweiterungen) ---
@Override
public void executeText(MessageReceivedEvent event, String[] args) {
if (args.length == 0) {
event.getChannel().sendMessage(outputFormatter.formatError("Verwendung: `!roll <notation> [+<modifikator>]` oder `!r <notation> [+<modifikator>]`")).queue();
return;
}
String notation = args[0];
int modifier = 0;
// Versuche, einen optionalen Modifikator zu parsen, wenn mehr Argumente vorhanden sind
if (args.length > 1) {
// Kombiniere die restlichen Argumente zu einem String und versuche zu parsen
String modifierPart = String.join("", Arrays.copyOfRange(args, 1, args.length));
try {
if (modifierPart.startsWith("+") || modifierPart.startsWith("-")) {
modifier = Integer.parseInt(modifierPart); // Parser handhabt +/-
} else {
// Wenn es keine + oder - gibt, aber weitere Argumente, behandle es als Fehler
event.getChannel().sendMessage(outputFormatter.formatError("Ungültiger Modifikator-Format. Verwende `+4` oder `-2`.")).queue();
return;
}
} catch (NumberFormatException e) {
event.getChannel().sendMessage(outputFormatter.formatError("Ungültiger Modifikator: '" + modifierPart + "'. Bitte gib eine Zahl ein.")).queue();
return;
}
}
try {
SimplerollLogic.RollResult result = rollLogic.performRoll(notation, modifier);
// EmbedBuilder response = outputFormatter.DCDefaultOutput(getEffectiveName(event) + result.getTitle(), result.getDescription(), result.isGlitch());
EmbedBuilder response = outputFormatter.DCDefaultOutput(getEffectiveName(event) + result.getTitle(), result.getDescription(), false);
event.getChannel().sendMessageEmbeds(response.build()).queue();
} catch (IllegalArgumentException e) {
event.getChannel().sendMessage(outputFormatter.formatError(e.getMessage())).queue();
} catch (Exception e) {
System.err.println("Fehler beim Ausführen von Text-Befehl roll/r: " + e.getMessage());
e.printStackTrace();
event.getChannel().sendMessage(outputFormatter.formatError("Ein unerwarteter Fehler ist beim Würfeln aufgetreten.")).queue();
}
}
@Override
public CommandData getSlashCommandData() {
return null;
}
private String getEffectiveName(MessageReceivedEvent event) {
if (event.getMember() == null) {
return "";
}
return event.getMember().getEffectiveName() + " ";
}
}

View File

@ -0,0 +1,119 @@
package de.ocame.wuerfelbot.Simpleroll;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class SimplerollLogic {
// Eine einzige Instanz von Random für alle Würfeloperationen
private final Random random;
// Pattern für Notationen wie "9d4" oder "3w8"
private static final Pattern DICE_NOTATION_PATTERN = Pattern.compile("(\\d+)[dw](\\d+)");
public SimplerollLogic() {
this.random = new Random();
}
/**
* Führt einen Würfelwurf basierend auf der Notation und einem optionalen Modifikator durch.
*
* @param notation Die Würfelnotation (z.B. "9", "9d4", "3w8").
* @param modifier Ein optionaler Integer-Modifikator, der zur Gesamtsum addiert wird.
* @return Ein {@link RollResult}-Objekt mit den detaillierten Ergebnissen.
* @throws IllegalArgumentException Wenn die Notation ungültig ist oder andere Parameterfehler auftreten.
*/
public RollResult performRoll(String notation, int modifier) {
if (notation == null || notation.trim().isEmpty()) {
throw new IllegalArgumentException("Würfelnotation darf nicht leer sein.");
}
int numberOfDice;
int sides;
String parsedNotation = notation.trim().toLowerCase(); // Normalize input
Matcher matcher = DICE_NOTATION_PATTERN.matcher(parsedNotation);
if (matcher.matches()) {
// Format: XdY oder XwY (z.B. "9d4", "3w8")
numberOfDice = Integer.parseInt(matcher.group(1));
sides = Integer.parseInt(matcher.group(2));
} else {
// Format: X (z.B. "9") -> Würfelt X W6
try {
numberOfDice = Integer.parseInt(parsedNotation);
sides = 6; // Standard: W6, wenn nur Anzahl angegeben
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Ungültige Würfelnotation: '" + notation + "'. Erwartet wird Zahl (z.B. 9) oder NdS (z.B. 9d4).");
}
}
if (numberOfDice < 1 || numberOfDice > 1000) { // Angemessene Grenzen festlegen
throw new IllegalArgumentException("Anzahl der Würfel muss zwischen 1 und 1000 liegen.");
}
if (sides < 2 || sides > 1000) { // Angemessene Grenzen festlegen (mind. 2 Seiten, max 1000)
throw new IllegalArgumentException("Würfel müssen mindestens 2 und höchstens 1000 Seiten haben.");
}
List<Integer> rolls = new ArrayList<>(numberOfDice);
int sum = 0;
for (int i = 0; i < numberOfDice; i++) {
int roll = random.nextInt(sides) + 1; // Würfelt 1 bis 'sides'
rolls.add(roll);
sum += roll;
}
// Addiere den Modifikator zur Summe
sum += modifier;
return new RollResult(rolls, sum, notation + "w" + sides, modifier);
}
/**
* Innere Klasse zum Kapseln der Würfelergebnisse.
*/
public static class RollResult {
private final List<Integer> rolls;
private final int sum;
private final String notation;
private final int modifier;
public RollResult(List<Integer> rolls, int sum, String notation, int modifier) {
this.rolls = rolls;
this.sum = sum;
this.notation = notation;
this.modifier = modifier;
}
public List<Integer> getRolls() {
return rolls;
}
public int getSum() {
return sum;
}
public String getNotation() {
return notation;
}
public int getModifier() {
return modifier;
}
public String getDescription() {
return "(" + rolls.stream().map(String::valueOf)
.collect(Collectors.joining(", ")) + ")";
}
public String getTitle() {
String message = "%rolls%: %hits%";
return message.replace("%rolls%", rolls.size() + (modifier!=0 ? (modifier<0?"-":"+") + modifier : "")).replace("%hits%", Integer.toString(sum));
}
}
}

View File

@ -2,6 +2,7 @@ package de.ocame.wuerfelbot.commands;
import de.ocame.wuerfelbot.Earthdawn.EarthdawnCommand;
import de.ocame.wuerfelbot.Simpleroll.SimplerollCommand;
import de.ocame.wuerfelbot.core.LoggerUtil;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
@ -33,6 +34,9 @@ public class CommandManager {
// Füge deine Befehlsimplementierungen hier hinzu
//addCommand(new SimpleRollCommand());
addCommand(new EarthdawnCommand());
SimplerollCommand simplerollCmd = new SimplerollCommand();
addCommand(simplerollCmd); // Registriert unter "roll"
commands.put("r", simplerollCmd); // Alias für SimpleRollCommand
// Hier können wir auch die Slash-Befehle bei Discord registrieren
updateSlashCommands();

View File

@ -34,6 +34,8 @@ public class DiceOutputFormatter {
/**
* Formatiert ein allgemeines Würfelergebnis.
* nur für tests
*
* @param result Das Ergebnis des Würfels.
* @param notation Die Würfelnotation (z.B. "1d6").
* @return Der formatierte String.