Skip to content

Commit

Permalink
Warning if there are no dice in expression (#342)
Browse files Browse the repository at this point in the history
  • Loading branch information
twonirwana authored Oct 14, 2023
1 parent 5decbd3 commit 412c0e2
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import de.janno.discord.bot.BotMetrics;
import de.janno.discord.bot.persistance.Mapper;
Expand Down Expand Up @@ -29,6 +30,7 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static de.janno.discord.bot.command.BaseCommandOptions.*;
import static de.janno.discord.connector.api.BottomCustomIdUtils.CUSTOM_ID_DELIMITER;
Expand Down Expand Up @@ -376,7 +378,11 @@ Mono<Void> deleteOldAndConcurrentMessageAndData(
log.info("{}: '{}'",
event.getRequester().toLogString(),
commandString.replace("`", ""));
return event.reply(commandString, false)
String replayMessage = Stream.of(commandString, getConfigWarnMessage(config).orElse(null))
.filter(s -> !Strings.isNullOrEmpty(s))
.collect(Collectors.joining(" "));

return event.reply(replayMessage, false)
.then(Mono.defer(() -> {
final Optional<MessageConfigDTO> newMessageConfig = createMessageConfig(configUUID, guildId, channelId, config);
newMessageConfig.ifPresent(persistenceManager::saveMessageConfig);
Expand All @@ -392,6 +398,10 @@ Mono<Void> deleteOldAndConcurrentMessageAndData(
return Mono.empty();
}

protected @NonNull Optional<String> getConfigWarnMessage(C config) {
return Optional.empty();
}

protected @NonNull List<CommandDefinitionOption> getStartOptions() {
return ImmutableList.of();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
@Value
@Builder
public class RollAnswer {
private static final String MINUS = "\u2212";
@NonNull
AnswerFormatType answerFormatType;
@NonNull
Expand All @@ -31,6 +30,8 @@ public class RollAnswer {
List<RollResults> multiRollResults;
@Nullable
Supplier<? extends InputStream> image;
@Nullable
String warning;

public String toShortString() {
String fieldStringList = Optional.ofNullable(multiRollResults)
Expand All @@ -39,10 +40,10 @@ public String toShortString() {
.toList().toString())
.orElse(null);
return String.format("%s=%s", expression,
Joiner.on(",").skipNulls().join(result, rollDetails, errorMessage, fieldStringList))
Joiner.on(",").skipNulls().join(result, rollDetails, errorMessage, warning, fieldStringList))
.replace("▢", "0")
.replace("+", "+")
.replace(MINUS, "-")
.replace("−", "-") //minus is not hyphen-minus
.replace("*", "");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import de.janno.discord.bot.command.*;
Expand Down Expand Up @@ -208,12 +209,27 @@ private List<ComponentRowDefinition> createButtonLayout(UUID configUUID, CustomD
return COMMAND_NAME;
}

@Override
protected @NonNull Optional<String> getConfigWarnMessage(CustomDiceConfig config) {
return Optional.ofNullable(Strings.emptyToNull(config.getButtonIdLabelAndDiceExpressions().stream()
.map(b -> {
String warning = diceSystemAdapter.answerRollWithGivenLabel(b.getDiceExpression(), null, false, DiceParserSystem.DICE_EVALUATOR, config.getAnswerFormatType(),
config.getDiceStyleAndColor()).getWarning();
if (!Strings.isNullOrEmpty(warning)) {
return "`%s`: %s".formatted(b.getDiceExpression(), warning);
}
return null;
})
.filter(s -> !Strings.isNullOrEmpty(s))
.distinct()
.collect(Collectors.joining(", "))));
}

@Value
static class ButtonIdAndExpression {
@NonNull
String buttonId;
@NonNull
String expression;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import de.janno.discord.bot.BotMetrics;
import de.janno.discord.bot.command.AnswerFormatType;
import de.janno.discord.bot.command.RollAnswer;
Expand Down Expand Up @@ -32,6 +33,8 @@
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static de.janno.discord.bot.command.channelConfig.ChannelConfigCommand.DIRECT_ROLL_CONFIG_TYPE_ID;

Expand All @@ -41,13 +44,18 @@ public class DirectRollCommand implements SlashCommand {
public static final String ROLL_COMMAND_ID = "r";
protected static final String ACTION_EXPRESSION = "expression";
private static final String HELP = "help";
protected final boolean removeSlash;
private final DiceEvaluatorAdapter diceEvaluatorAdapter;
private final PersistenceManager persistenceManager;
protected boolean removeSlash = true;

public DirectRollCommand(PersistenceManager persistenceManager, CachingDiceEvaluator cachingDiceEvaluator) {
this(persistenceManager, cachingDiceEvaluator, true);
}

public DirectRollCommand(PersistenceManager persistenceManager, CachingDiceEvaluator cachingDiceEvaluator, boolean removeSlash) {
this.diceEvaluatorAdapter = new DiceEvaluatorAdapter(cachingDiceEvaluator);
this.persistenceManager = persistenceManager;
this.removeSlash = removeSlash;
}

@Override
Expand Down Expand Up @@ -124,7 +132,10 @@ DirectRollConfig deserializeConfig(ChannelConfigDTO channelConfigDTO) {

RollAnswer answer = diceEvaluatorAdapter.answerRollWithOptionalLabelInExpression(expressionWithOptionalLabelsAndAppliedAliases, DiceSystemAdapter.LABEL_DELIMITER, config.isAlwaysSumResult(), config.getAnswerFormatType(), config.getDiceStyleAndColor());

return Flux.merge(removeSlash ? Mono.defer(event::acknowledgeAndRemoveSlash) : event.reply(commandString, true),
String replayMessage = Stream.of(commandString, answer.getWarning())
.filter(s -> !Strings.isNullOrEmpty(s))
.collect(Collectors.joining(" "));
return Flux.merge(removeSlash && Strings.isNullOrEmpty(answer.getWarning()) ? Mono.defer(event::acknowledgeAndRemoveSlash) : event.reply(replayMessage, true),
Mono.defer(() -> event.createResultMessageWithEventReference(RollAnswerConverter.toEmbedOrMessageDefinition(answer))
.doOnSuccess(v ->
log.info("{}: '{}'={} -> {} in {}ms",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ public class ValidationCommand extends DirectRollCommand {
private final DiceEvaluatorAdapter diceEvaluatorAdapter;

public ValidationCommand(PersistenceManager persistenceManager, CachingDiceEvaluator cachingDiceEvaluator) {
super(persistenceManager, cachingDiceEvaluator);
super(persistenceManager, cachingDiceEvaluator, false);
this.diceEvaluatorAdapter = new DiceEvaluatorAdapter(cachingDiceEvaluator);
removeSlash = false;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.janno.discord.bot.dice;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import de.janno.discord.bot.BotMetrics;
import de.janno.discord.bot.command.AnswerFormatType;
Expand All @@ -16,8 +17,10 @@

import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static de.janno.discord.bot.dice.DiceSystemAdapter.LABEL_DELIMITER;

Expand Down Expand Up @@ -141,6 +144,7 @@ public RollAnswer answerRollWithGivenLabel(String expression,
.expression(expression)
.expressionLabel(label)
.image(diceImage)
.warning(getWarningFromRoll(rolls))
.result(getResult(rolls.get(0), sumUp))
.rollDetails(rolls.get(0).getRandomElementsString())
.build();
Expand All @@ -152,6 +156,7 @@ public RollAnswer answerRollWithGivenLabel(String expression,
.answerFormatType(answerFormatType)
.expression(expression)
.expressionLabel(label)
.warning(getWarningFromRoll(rolls))
.multiRollResults(multiRollResults)
.build();
}
Expand All @@ -168,4 +173,17 @@ public boolean validExpression(String expression) {
return cachingDiceEvaluator.get(expression).isValid();
}

private String getWarningFromRoll(List<Roll> rolls) {
return Strings.emptyToNull(rolls.stream()
.map(r -> {
if (r.getRandomElementsInRoll().getRandomElements().isEmpty()) {
return "did not contain any random element, try `d20` to roll a 20 sided die";
}
return null;
})
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.joining(", ")));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class CustomDiceCommandMockTest {
@BeforeEach
void setup() throws IOException {
File cacheDirectory = new File("imageCache/");
if(cacheDirectory.exists()){
if (cacheDirectory.exists()) {
FileUtils.cleanDirectory(cacheDirectory);
}
messageIdCounter = new AtomicLong(0);
Expand All @@ -56,7 +56,7 @@ void setup() throws IOException {
@AfterEach
void cleanUp() throws IOException {
File cacheDirectory = new File("imageCache/");
if(cacheDirectory.exists()){
if (cacheDirectory.exists()) {
FileUtils.cleanDirectory(cacheDirectory);
}
}
Expand Down Expand Up @@ -298,6 +298,25 @@ void slash_start() {
"createButtonMessage: MessageDefinition(content=Click on a button to roll the dice, componentRowDefinitions=[ComponentRowDefinition(buttonDefinitions=[ButtonDefinition(label=1d6, id=custom_dice1_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false), ButtonDefinition(label=Attack, id=custom_dice2_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false), ButtonDefinition(label=3d10,3d10,3d10, id=custom_dice3_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false)])])");
}

@Test
void slash_start_warn() {
CustomDiceCommand underTest = new CustomDiceCommand(persistenceManager, new DiceParser(), new CachingDiceEvaluator(new RandomNumberSupplier(0), 1000, 0));

SlashEventAdaptorMock slashEvent = new SlashEventAdaptorMock(List.of(CommandInteractionOption.builder()
.name("start")
.option(CommandInteractionOption.builder()
.name("buttons")
.stringValue("1d6;1d20@Attack;3d10,3d10,3d10;3;'a'")
.build())
.build()));
underTest.handleSlashCommandEvent(slashEvent, () -> UUID.fromString("00000000-0000-0000-0000-000000000000")).block();

assertThat(slashEvent.getActions()).containsExactlyInAnyOrder(
"reply: commandString `3`: did not contain any random element, try `d20` to roll a 20 sided die, `'a'`: did not contain any random element, try `d20` to roll a 20 sided die",
"createButtonMessage: MessageDefinition(content=Click on a button to roll the dice, componentRowDefinitions=[ComponentRowDefinition(buttonDefinitions=[ButtonDefinition(label=1d6, id=custom_dice1_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false), ButtonDefinition(label=Attack, id=custom_dice2_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false), ButtonDefinition(label=3d10,3d10,3d10, id=custom_dice3_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false), ButtonDefinition(label=3, id=custom_dice4_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false), ButtonDefinition(label='a', id=custom_dice5_button00000000-0000-0000-0000-000000000000, style=PRIMARY, disabled=false)])])"
);
}

@Test
void slash_targetChannelTheSame_error() {
CustomDiceCommand underTest = new CustomDiceCommand(persistenceManager, new DiceParser(), new CachingDiceEvaluator(new RandomNumberSupplier(0), 1000, 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ void roll_default() {
"createResultMessageWithEventReference: EmbedOrMessageDefinition(title=1d6 ⇒ 1, descriptionOrContent=, fields=[], hasImage=true, type=EMBED)");
}

@Test
void roll_warn() {
DirectRollCommand directRollCommand = new DirectRollCommand(persistenceManager, new CachingDiceEvaluator(new RandomNumberSupplier(0), 1000, 0));

SlashEventAdaptorMock slashEvent = new SlashEventAdaptorMock(List.of(CommandInteractionOption.builder()
.name("expression")
.stringValue("20")
.build()));
directRollCommand.handleSlashCommandEvent(slashEvent, () -> UUID.fromString("00000000-0000-0000-0000-000000000000")).block();


assertThat(slashEvent.getActions()).containsExactlyInAnyOrder(
"reply: commandString did not contain any random element, try `d20` to roll a 20 sided die",
"createResultMessageWithEventReference: EmbedOrMessageDefinition(title=20 ⇒ 20, descriptionOrContent=, fields=[], hasImage=false, type=EMBED)"
);
}


@Test
void help() {
DirectRollCommand directRollCommand = new DirectRollCommand(persistenceManager, new CachingDiceEvaluator(new RandomNumberSupplier(0), 1000, 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,4 +470,13 @@ void getImageForRoll_polyhedral_RdD() throws ExpressionException, IOException {
assertThat(res).isNotNull();
assertThat(getDataHash(res)).isEqualTo("de01222cf4ea85e2fe2eea6539ebdfe9809bfe88f6dfb8ece5736df9eeb6603d");
}

@Test
void getImageForRoll_polyhedral_RdD_specialColor() throws ExpressionException {
List<Roll> rolls = new DiceEvaluator(new GivenNumberSupplier( 99), 1000).evaluate("1d100");

Supplier<? extends InputStream> res = underTest.getImageForRoll(rolls, new DiceStyleAndColor(DiceImageStyle.polyhedral_RdD, "special"));

assertThat(res).isNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
@AllArgsConstructor
public class EmbedOrMessageDefinition {

//todo ephemeral field

String title;
String descriptionOrContent;
@Singular
@NonNull
List<Field> fields;
Supplier<? extends InputStream> image;

Expand Down

0 comments on commit 412c0e2

Please sign in to comment.